From 0c889b8f79ed1fed47b1bf71f7de44d4995206c5 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Thu, 8 Jan 2026 18:53:27 +0900 Subject: [PATCH 01/17] teddsa_addon: add extractKeyPackageSharesEd25519 --- crypto/teddsa/teddsa_addon/addon/index.d.ts | 9 ++ crypto/teddsa/teddsa_addon/addon/index.js | 4 +- .../teddsa/teddsa_addon/addon/src/keygen.rs | 102 +++++++++++++- .../addon/teddsa-addon.darwin-arm64.node | Bin 796304 -> 814624 bytes .../teddsa/teddsa_addon/src/server/index.ts | 12 ++ .../teddsa_addon/src/tests/keygen.test.ts | 130 +++++++++++++++++- 6 files changed, 254 insertions(+), 3 deletions(-) diff --git a/crypto/teddsa/teddsa_addon/addon/index.d.ts b/crypto/teddsa/teddsa_addon/addon/index.d.ts index 9929abd1b..8e5d32804 100644 --- a/crypto/teddsa/teddsa_addon/addon/index.d.ts +++ b/crypto/teddsa/teddsa_addon/addon/index.d.ts @@ -19,6 +19,15 @@ export interface NapiCentralizedKeygenOutput { export declare function napiKeygenCentralizedEd25519(): NapiCentralizedKeygenOutput /** Import an existing Ed25519 secret key and split it into threshold shares. */ export declare function napiKeygenImportEd25519(secretKey: Array): NapiCentralizedKeygenOutput +/** Extract signing_share and verifying_share from a serialized key_package. */ +export interface NapiKeyPackageShares { + signing_share: Array + verifying_share: Array +} +/** Extract signing_share and verifying_share from a serialized Ed25519 key_package. */ +export declare function napiExtractKeyPackageSharesEd25519(keyPackageBytes: Array): NapiKeyPackageShares +/** Reconstruct a key_package from signing_share, verifying_share, identifier, and verifying_key. */ +export declare function napiReconstructKeyPackageEd25519(signingShare: Array, verifyingShare: Array, identifier: Array, verifyingKey: Array, minSigners: number): Array /** Output from a signing round 1 (commitment) */ export interface NapiSigningCommitmentOutput { nonces: Array diff --git a/crypto/teddsa/teddsa_addon/addon/index.js b/crypto/teddsa/teddsa_addon/addon/index.js index 115a4f1d0..fea56d1ea 100644 --- a/crypto/teddsa/teddsa_addon/addon/index.js +++ b/crypto/teddsa/teddsa_addon/addon/index.js @@ -310,10 +310,12 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { napiKeygenCentralizedEd25519, napiKeygenImportEd25519, napiSignRound1Ed25519, napiSignRound2Ed25519, napiAggregateEd25519, napiVerifyEd25519 } = nativeBinding +const { napiKeygenCentralizedEd25519, napiKeygenImportEd25519, napiExtractKeyPackageSharesEd25519, napiReconstructKeyPackageEd25519, napiSignRound1Ed25519, napiSignRound2Ed25519, napiAggregateEd25519, napiVerifyEd25519 } = nativeBinding module.exports.napiKeygenCentralizedEd25519 = napiKeygenCentralizedEd25519 module.exports.napiKeygenImportEd25519 = napiKeygenImportEd25519 +module.exports.napiExtractKeyPackageSharesEd25519 = napiExtractKeyPackageSharesEd25519 +module.exports.napiReconstructKeyPackageEd25519 = napiReconstructKeyPackageEd25519 module.exports.napiSignRound1Ed25519 = napiSignRound1Ed25519 module.exports.napiSignRound2Ed25519 = napiSignRound2Ed25519 module.exports.napiAggregateEd25519 = napiAggregateEd25519 diff --git a/crypto/teddsa/teddsa_addon/addon/src/keygen.rs b/crypto/teddsa/teddsa_addon/addon/src/keygen.rs index b10ac33a9..97c14db5e 100644 --- a/crypto/teddsa/teddsa_addon/addon/src/keygen.rs +++ b/crypto/teddsa/teddsa_addon/addon/src/keygen.rs @@ -64,7 +64,9 @@ fn keygen_centralized_inner() -> std::result::Result std::result::Result { +fn keygen_import_inner( + secret: [u8; 32], +) -> std::result::Result { let mut rng = OsRng; let max_signers = 2; let min_signers = 2; @@ -136,3 +138,101 @@ pub fn napi_keygen_import_ed25519(secret_key: Vec) -> Result, + #[napi(js_name = "verifying_share")] + pub verifying_share: Vec, +} + +/// Extract signing_share and verifying_share from a serialized Ed25519 key_package. +#[napi] +pub fn napi_extract_key_package_shares_ed25519( + key_package_bytes: Vec, +) -> Result { + let key_package = KeyPackage::deserialize(&key_package_bytes).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize key_package: {:?}", e), + ) + })?; + + let signing_share_bytes = key_package.signing_share().serialize(); + let verifying_share_bytes = key_package + .verifying_share() + .serialize() + .map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to serialize verifying_share: {:?}", e), + ) + })? + .to_vec(); + + Ok(NapiKeyPackageShares { + signing_share: signing_share_bytes.to_vec(), + verifying_share: verifying_share_bytes, + }) +} + +/// Reconstruct a key_package from signing_share, verifying_share, identifier, and verifying_key. +#[napi] +pub fn napi_reconstruct_key_package_ed25519( + signing_share: Vec, + verifying_share: Vec, + identifier: Vec, + verifying_key: Vec, + min_signers: u16, +) -> Result> { + use frost::keys::{SigningShare, VerifyingShare}; + use frost::Identifier; + use frost::VerifyingKey; + + let identifier = Identifier::deserialize(&identifier).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize identifier: {:?}", e), + ) + })?; + + let signing_share = SigningShare::deserialize(&signing_share).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize signing_share: {:?}", e), + ) + })?; + + let verifying_share = VerifyingShare::deserialize(&verifying_share).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize verifying_share: {:?}", e), + ) + })?; + + let verifying_key = VerifyingKey::deserialize(&verifying_key).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize verifying_key: {:?}", e), + ) + })?; + + let key_package = KeyPackage::new( + identifier, + signing_share, + verifying_share, + verifying_key, + min_signers, + ); + + let key_package_bytes = key_package.serialize().map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to serialize key_package: {:?}", e), + ) + })?; + + Ok(key_package_bytes) +} diff --git a/crypto/teddsa/teddsa_addon/addon/teddsa-addon.darwin-arm64.node b/crypto/teddsa/teddsa_addon/addon/teddsa-addon.darwin-arm64.node index f0b9be05377f47010920235a091b37d2bcf74c32..e71fa80315c0d6677134fc41073c84c22a98c3ea 100755 GIT binary patch delta 156520 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

    K8 zN@4%u>4oYIS#tW~yU`>(w)S5ye!;Jm>ZQG4|&1 zQPlqb_#`va-JbNm+udz}UbNgtIeLMBm8*z~pxA=Sseth2@S+8jQ|Uzh`E4d!YV4-#_-TljN0GUU?;XC3)qQSIn6U!d&?9 zHR6h_h7VukTd^8GeDRIlp6SEah@Yw&K75VuTyYP)!H2IA7dp$*#D}jD8R;oHW%=BS zmRe&UzD61x2ODV_EwvLu1^{6eG)k}ZGJW_OFuy2<4`1WEuhlT0G`{0iapT@3eukTo zcjPS0vBHP10kB-r0`cwcbSP}ZDejsKVnz*h*G}R8i;Nc9NoT=tBCqh_YrtJMoKBR* zU>?tQ#lb_DATS1ScbRc`n#%OyYvlO^9*%{(B_m)pDVhxgE+4)|{M0)LsAwQStX6~% zU%-Yo_<7}*uH;@FbXVm{2q@t zDU7DjB9TX&78TD)-H7#1p|v1EW9}Incfj0XC-#2A=487ZgqKZ2sM#JK#aB(Dls$YX z{hGxRecjSU2}~0urk?|yi__U4-s>9unvT(U*kar#n1z)NZuP}$C0|PWh4$~{U}48` z@%#B)!s;fV42Cg=g1H)Sj*K|XfX|OZLj;u#X#&f%OMpFynOaPVIQi1fBh0}_BMd51 z@NP{o!palow260y?SB9lB~(ZM<2v5eBIl3H4Q*-h^CO0z0dAEzVG6-ch|^xL9al z#lai6glZhBnTJjNEtHbQ!khO7#f_`D^_p45C7@PR8&wRX3=0c%Unv}D0mBWN+>?dG zv_VE&Ktol9*CSEY=TOxd$UNPsY77lcXU%!B5&fD_j>OzU!teC}dttRMBiiw)$H-ROM{)Se?+e zR}7>1rbs1d%q9(@Q++TUcfLZu4#IHzTBX~ASW=H)g0wuK>IM{lqs;qY6K8rfGrQGR zuvx6r3~5pkqA`e_%Rlxk6~(?ah*tE)%4t35%3;yTTTj58b5~ZXEzH@AVwg5k#&sy@ z)vT(`-{#lQyB;F%yV(PL`3ZXbZuSJKQ6|tDa9nb{d(Tl@+{lRpRG?IAS#WAZC~N`i2m92R}xdXx}q{ zk7p1+J!LHk6%u@Z6L~JfrHavjrWi6BP>jiUjC`$eLL(y+IzzNGQ&*QPLR=W)x`8l5 z76EY(CEUYo+)btIdsw)~7qFau0?GZx(UbSE7h~Q;_-=&b$H4*v<+`%saZ z!Tqoy`kC_jv4H4p=-oAFBP+{%KLAy*v4C^9`7%TtO3CAB#C>SDGKD_whpzCZLO+ZD zTbJpE_!@vjgc48lK(YECJ!*j$p1hW#z@eM)&CqLt!YON z3*iZjeC}rV^T(>in1~@vX8k+fF)X5;wfO%V7C{3V4U39~VG%drzlMdgevOC4y8iz? zEaoBY&S7yKCsF^`u$XD&^K2Lv=V<@EEWrO1@-`j`$0bU<2mSB>H;2Mfq>G^tHpUzZ z@E~ang)5_*4uvr6lEqNCFxnUj?bZQKc+?at1D8``tRnt%TvU!W$HjDRj*E%h92fg8 znd9OSZjKAsh#BLebPOwc3pA|3Z>jHZ@fp>a1022~+UG)nQ=Fuoh&7kkv(aHaaW39? zt!KbWA;$Vqq>t`_C7igiLxb*Tec2=Q+Wl}T9#%!)-j6M)Cx7iq*NIAqRim3zGLX|Nh~_iSLAJmyl|r~%y&duAH;1IN9veLguzJ+aJ6Q% zX%b6`@fYyMlpI+07x31_veasvqaTmOvKH~SF?4$piy84V(oQ(z#3lFR*is%uT(xJf z(i1&R8g?W67xEfTL;>S+A}Skf6w`iSS-`*0a#Nz`C$n}jqWc^5zEanr8cia6iJLTs z7&M=f==;emWx&sfug3X>D0h|wBXji9tc$^BFU?5OAo&LO9cgZXm%-~u0kjV|CEsiV zexadg%!e-}8t@cLoCROs;6p%}H(+c-rO9K2pDzIm+)_VZEfYAgnMgc?a6%>?IfTAH zY3!IT+3uc;GVscc0f$#D#41LpA&qc+fUzSszRTgs7fX%$w7>l{M+5Avi_-7DT0uj^ zMak~3IT~m9+)vxlIQ?1QreP(ZF~W-y-YRMWKg7?F`Sk?!3TTu*3$?s%x(crc$S@a2 z_2CJDT1jI99`)Dq8WR|KCxHP?E0li+zCynSe60nWivu;`owdHecLJIgAmL3)G=oT| z!krK-eTT92X~xJa#%6a8?q2ng_U|2nJ63K|Z2~~WTHHv_h(~WW)06Kp_YETa^DRml z&Vu_HFu8Do;>1x29OC+_7@Y#{Yv;Qk_hVG&JjROlo`fr2=P%?G-q(7RK~dl&t@157 zP;ZmZlHI%ucJ!!%H_IB_#*tpo$GylN=X^Yr<@4D{>$FE%(X}}Wd^s;h5M?|}x+y(EQ3FJMtYN(<p*;bC{f%rYM*{=(B9W4H_e z7ahlYX4Jk+-V0g8KT$ebQ@4dc`CW4-$~g@vzoaJ?vf(^1g7z(hMk(%5@>#^91F%55 zn6STxRtmEAqVz;Z3Z*Xsj+b3HcJX?$UZly3*r>4muzqYf02bzSL56ksIy%3Ig?JLK zEdK;lp=;8p*=lP5)pqheU$ey!~3tGpl*p&3%7*gDZ1L~Szyj6MH7Or*(mz;Wo%=PP}C9@ z!R?9EbqNe$yN{y#mq4l4eiS{ugeCrKvHBADcz@DaY%yFRxZ30K=Je+hHiErRIfd-S zmhi+0|1&WATAFJ@gWQ)`RqRv}AFuaxX472^72G!lT-(L>i$%PP{ES#ySj2_}y(G*cMSsEzNuoa;$Ik1(KT)9@#VrG>Ko=_9 zL2;q-ilt%8pg4Unl(sAbm!J5T>?ua}u!9aKC1!RwAxhW20m`lP@G@qj8LzS~JUo=% ze-&>bSwiXdt88%l9(m>>*>$4*CJY_o!L&1@xK@fgJLs;JW_Jx0-L*Wiq&3YU<_Lb) zRT%aqpw%dBY7Bi$Y*^|laCqwj9ZRo-NVQw#;OixVJ+T?JFC|JvXR$HL{;O_t37n;4 zfQxA!x*W7FHd7x_|K+Tcn-MOh1N-jTVtP`2kAF>gwr4$qeg^9pPl2pZ1@AQ6)Zhz2nZIt zB^MWBaLSHlU}3|#es?ica1Em!jbFhWK|AfROm)`Ub+G?2m8@W+c#I#ptz?7Q^Cs%s zk2FQi|1Z=N{sr};0(HdF-+%QY`|IpOZhM3dz0MNZPGYNAn+`3a>#uZ4+K%p0VL|tJ zoFPMzX82Kc5xV{a)Ma25-h(KbO4=JNh@M^ro&FP#(8sG-68|)cPOoAKvu47M8PO z$mY;6O@(6!>+s7FP7U&=+axj)a+s5dw}|{#nyaSw&9v! z=x{7JovsP)8*U`~y^Z7qGdZqNa`WNz#@o1=m*oY^WEF#6K#!yH(Yu>CdE2F(3X&hL{ zZ5@isTWI-m){^~1S~+XY&eD!@7SpUy$YNvBu}jukM$(_t=tOwtknqzvcmVA$tm~)g9=b_gR$ft8nl*9X4db!QmWCF8AUH z@qsQTP+kX0`V{ADt3G8Gwv9^PXR|`i<51mLfu|WOaIxYpOenBX`Ufn-w=$sw#-nk~ z>a#ETfH~UDL>bn6+)o%GO)hFTKfKC@^3qWr7DE^@V(2!h(zpmZ{sFtor!cEnn0bf^ zIk4i8k%&L3&nhs?&#)8-FZ%ch)&kD#+3ve~Q$O@5Ds(A>?97_n|Md&R#I57uKp zXz*Z*;6d0wd9VdMFo0O6raaifh@GZP9nbWo+C{CyXp+um`WO{=ug|l6D|7Hi!YKSB zmf~L`HnNS{tY0_{`-s)~1fWqyIm>Z$6y-R$97YSbvJ{I^I2u48V(0bhtt^T8)gwYv z7R!A9N{ZUXHn0=4cN??EfCS@0d2Cydq2RVFTE;I;TOZfXB&(!7d47T-hJ{kfCoICp z&xW@0H`7qk10t}4DaB&LqA^#= z;i_#xyAH8zpG$#S%{o;Gr*dmvH;VWX3*}e+#PY%19=OVWnR0$)gMG?frHV!QF?#Pu zG|Nv1*%U>TK?4u5oR03#`QAI$B6T>1^TT{ViPhynd}mms578~ltqF1UYc**HUP`FQ z?>?Un9%5aZ5L0as6K^8!^CN59aV?PSbS`n%;$OIqcnAMu{H2*fZ#_ns=OB!JUQcEL zZTu1YTXf-lKMErtL1mwx*z6`n<#jje?OEzuUvH8Rv$hb49S>tZNTR&M%$}GTuO&gc ze2qFRek@))k9wthOOwAv_}hYb?K^}k@$I`Jo;DnYp4(xguMV@s=uDgDiG1k}X|j*xD@7x-!=piixFYl-Keqo`} zx8m!iQ@oH)&V7Tk-RSf$cw;UN*@QpdE)g9YAxOe^#f`en2A`_B)A*y15e`~#l#MhQ zbm1uL$ZwpcmcO!>ZNHobG`g55`g?p=#haT1qbaq7rQP~P`^Ywkd_?ifq8X`)ak0rT)(VQ++JY$DYiW6oZZ zRK;>^;{alJI$6mT<%Tx`uT7$rRW9%^tI)&`P;C|K=G|T7a#GulGOJmzQf@t(Ov9_0 z-DJwFYWAGX17O9@ot1>|3a3jNgBf=vQN(cwD>VepXBqX=2zHS~GjlhLfzh33K2in8Hat#kzT1K55SEz53Cn860cm zQ!F{SQT}eO{8|ECDs&5=ic_qa6U`|Y+U-6`H%_tCB>06DX1~JgTX5NP+2*cEIKbY5 z0#eaGgo<7ClMN?n#A$49Uq4B2oQ9#=ODE~)(-=uF0MThILx#|&HEcBNN-fS{&Wt`u zn^wxPOFzx9P{kQ$hXH8y8K@tw|3)ci87#qQ>{&KgDcpR#2W>ygI0aDJhrE$OG=-lq?yT|b@K?aH)c3&SHJ61@kMv+gn zrIml6-xzJQ{STJF_nx4$f3W9JSZ+Fvzrdn+$q8C`f!%L|4{a)T3e|b|&P4}=POQv8 zRM3vCiYNutQA;lR1R$GM$)ouQ9Mqt4G z4LHa^p~N=AgE|>!1jhGI9qZ2sjBxXg^(uXYXBA3C?dw(Q20&i`I92dQ_?-^*I(-vC z`=;Smof;!7lpeYxy?clHGXf+3giej}&l2WWowX7)LOu1Lw>JzZ>cd4yZ(O^@9qU#2 z214Zy0^jP?v_ijiXo_z}hX#B}g3Wt6*Pjs>2!H6*w1D_7#u>pI z*ij{f>{nO^%WSa>N9P)Tg@yUGLZazlG|(7^4tn7V+s^;2rruXsSLFoGwyA0o52ICA znI}J7O=VYE%ee2VVc`R%gRn|+sYS#&6f7EybEvr}Vs1q`UAqcN_;EG0yoR&HcY#Z6 z7NoxPGj;?eNy znBMXPVVK?mDgPh~OSTaGBloa6AkwPeWAOrQ+z-Jn+#VX=YfLzk|zbnhOGvbU!m zwJ0?zwP~r()S}d|`cf-uS!9HNqij}uJ7-o=DqX9^(7jzn!8cfeudzw2iG%5p5V{2t zb-TqJo*k{M$W^HWH^8Y~Rm5+y_Qqm~1!T{QiavdW^K& zP{TkX{mq`gqaemaK`rX@jlKoB5KYT&vF`s-M%1gfVg7&p7^U21+2JRT)rANNQw=NG z9g<{N5ecpxJ4R3c&D!zrkI@&m;S^@qG0bbusc|d5b3IMTWDxJyjXKvgZoWFywB(qO z^1)PG2NUeQr|7df2=C);nJ0{r?_QS4(<8<GK~I1N9lbxe#kl0WLje3!5&f%%@}%;Oz&EFg8xg%AjShjCXP%CjuKw~N%Nj1 z5IODU|EG7f@`3CDbIjt-A$FE|fIS7O0xB9e3%%&U4>g+)R=8(!4b6#-B^Hf%`h$(5$GrG4 z=-2P^=1aW;fWlRIcm1R{Pgi{^er~A8mY?-@0el5xgXo(;Zi9=Z^MQOdv(rmKJRNsS zz6nC4mCgt8ULM5;pDMHL3Uv$SG5$NcX@(Yhom2`+a6yOD#9;m)-+!3)1@m!y%VFvi z!n-Pau=XcwFW!aT3E_5Lc$mHoL6Ku=Y$#7x9z2Xm3@^on(e6;*OsNpSKZWv0%R=DH zF0j(gP+rnY;II}n)2utTU$?pA!UW!F*&=m{T9=p?M|*I&0R?hyw6EYMbkaeJsJK(aT}Fu*Gv74BLu2wH=}&~X0f5F@ohyvQPzooL0x zabS}&`qo-H88CR3SFDaE<9hR*Wma6T8*&rZ`XVIBEVnY82gTXbwK*tqRI#c-3gaGw zyLKG=crj;c$GJ-#9GQUeCj}QGv{u`D~M#X0!RS}rztw`RXm&m&(t6%D#Yjqv| z!okzET~aE#XSp;r%~=DBSpx|*SR)w^4piYjx~m3~-Akj3;VP`8qxb}0qvc9`H1}J_ ztVS!m6UDm>oevgRt33>h=ITZ8r-RoK4ai1qTs=-2asb3kIc~P`7*x7uoYeUU;+{bp zk8!rKfD1&WjmmV7=AmXM8XC>xEk-%$MDwEgYs`%tHh#@}&X4H-V7m|qGpU80Kf*@R z3wEAmsdVIfXkWk%$j-xC3u1@KJv3KwRt!@V^L+q*5>8>N=6S&FO-SixjK0k~-6+Jt z@8Wxo&A8aLk#J9wN`Mp2>)WR2l{f^b4?HTGCl;=Lz}hjA1}kH)~3+yH_Dal0Z8 z2Wd|XpK4A0$=Ne|#UkE-7$d$6h{dt|A+w&p$MT=pVA|cB$FjTWOmm**RqiN~gz0?Y zD5(RrZ^2vG+8?T;|6w1K>)eIKBb=WieF)KkM{FgU-h#*bh?OPW$>3F{6MX+n%8cWo zw7Ugw7U2WvDm)!6e85z~@@u;|i$qRGl^b1XflajvfGe1~tDGx@8wWAzVpD3MU(2X< zOLQ?~;X1q}Z_BF=(#tJ*3tv2H)IqC@l}aH33s2iS(5{v|!S*dOZ^mAr*ts9rg>aR_ ziL8K&w+)@hI>!N7=|LJ7#}kv@0@yNS$#-UZ4dLQQxSf3IrNQeLzw?weL)vQ4vrMM# zap0pt&k3LieO{E{tX~G|w_YA94rvRiRXlGMihhL+nRoqQENCtb!Eh<0N%6pf;ZjIN z@jSzO2(U=#Q=(sGQ*}HK99bn!)dR}#LS~a=Q4SNHy8!(^%nG^A`ME2?6~3lhZIf+E z!+!id97dKGbRPp)Jmpkcvq-9i{4y%=KmuM%Z%)r8aGhWMfjTAfM9*_Sm=j0cE_XT> z1U<ZEm_()l^M@|Xi-9@Gz+8}%dbj>xnB9bY6`1L}Ry@Jv zK!&%0?s1?yj1zyO8otRqG(+^iJ#Y3;9do3v!xeDg`kjOp*Q2W^^y^eOxkf`6SjHq{ zI2paYD4F*OfHQKuW!}k@=T)$P_}~ZnBbh(W|2RPRr|_)A`J$CZ@%{J0TwN@6;(<(b z^4W+NHy)acFgUX12ilp!6WJ6xpMr(pSPE**Tk~ZX+K`_N-^c_jR-d#1-QwmMNPN zuJUk-&>XcvuI^EbYySKITn*dib}1fU8h!UYKDf`BXN z;)b+R-RN3-mr#x901NA<=&laD^P}VL$oYsM1-n2Da_kxK5I4vZI;iI0n~*ZaVtwyy zvzaYfQCqZ+5$9~PGab#i>G;Q#Jh&9_RMmk8`I{rN(Ah|ZV*FS-^30&NC~+pR3j^34 zpkM5iTG7KDc^bP&uXp4_`R~8zS3B}(#y{In!JYZHeBpjN)fwp#dW$Z6J7Yfj$yC0M z@pC`xFL&cVbAIMK8kfe?_|e09SsLHOpu~AF11sj9`fC|Hf(eyVCXA}9zoms)Ji0af z>J?^d7DHG44!##}w$$sYHzEA(ev6^2F2}d;S&PtBhgn|67V}$&p|Ezuopon{3lWjs zNOQdy;l)nPwSnb-7DIC#U=+cuhUVHx2(t>!^>UgL!c!>&OYsmqDR|MUrD|u;jm6;< zE;3y#im}j=Uc80HNX$v2ZN0GV!&bZ(`Vn?FZ|HU(KAVlAg1%tKL$nHiareO)hq1B3;!Esja*S|L*_-V}B9|=v@uKPSUGdco1c~^kMSQeq>#_a~HNyy=>dKHDNH_cOyDVeT`w|>p z)Tcl16kYAFm9_3(nuwVs8;<7JC-o>TO-d^r0~jl|v@82VJAw6ie;(=otcNxV(W9`w zFgkFR7g+}I9{kU*sP_Qgp66NVnE^bjYP!3x_q8Gq*D zaS5|O2GfZFytmJL-Z;IJoyGZ6=Yf1A|2vRY4&;x8j6`8sxjx!s_+JYlXA~;==pln3 zFfAqt{?sRjZ#4tO&B!vCXV#|-9L!%Z0~rByWH5g)K;LIx@veXsxq&?&`R|3h;&n)< zJ0g`{ImSw_V;fhBums+T)#>Ve^zywt%~?i(e&AmIDYqbdWmd5_(fxdY#{^GtpA5F1 zfpp=19u*7PD&b^SI}33v#;`a>KaL@JLiQ*#(sBc-^#d6D@9(AF5AYaXx|ha1z`EJS{&0G3x6mi4MxHY@!`O!SwXH6rx*LKs}qxl=`DgCZ7+`^j~ zOT;QkR1wFL!8Cjv4~sJ*ALV9bZirTmF?22gPyazEOP@0{UJ9X=05&o7az+*h)2?wm zkAM8R-f}#j#=J*<4tlzp^bDoa2|UjGJ`t5-M%_b4C-4aGdm2GylKKQE7OAg#g3n^< zcMzyKFm88X?e}jqZga&qqH*}df1z>CM9{c!7p`*fr@W`^0zIgqSRRa}$0qTf>_IA> zgd1r%_==(Q$=o3hStmn$V|Ou`-^2W9?_{2&xb1?%#-5F{r~HfD+te0c+G%QwPwk{> zPw@wVq9TM2JjGl1f3>rY%!jVb2Yf1alE)M%hu#L{6s#&2@1$R+V3k-v?o&B==K)+Q zHo5cwZJf$4ut-|d3qf zW1fEkH-LxB!NzWk5-{|+(aN4pAB4P9MZglf$zLmdPp>KJH=g0~S%tFOm zOCjj_g${d|CQJu6z$o3IK0i$FJd1xVw-I3Gd&=u9cpVD{m9yZPzmHT~pX~(G-hoNC zD_i?He1@k|30DjHyD#%0R>SLpZXteD4amSCli;E|CW;jq-%^Br?RB(ZeagYehLof? zcydF^3k@kWel<_EWQlQ~5l$Oc^8}wF9S!0fSqpVKzM3y&W9W%uKAH`ngT*}7`yK(| z?AYkVC43HZ=nG2Fi}{W%bi+*>-Mzx|%8!Jm*1nbEqs7y)q8azU^NaeLy5NVDEC7E6rweb zw9UK~o!P=C27Yiy=Jg0K&3~sk73w@bXjuaa%#Wt=)-WpB!UH@OIg$MmB8*3M$4C50 z291Y3l9q1e&+)o)^8XlO{#?0PX7`Y#aA-^mKjz7RDvqLUAM*|-{N;~%N4~Y361VZ* zUh4pV9aDht&q4Xu-JmQkr&qS|>3oL_3p?ILbpJ@b&nJ8>6MExMc@n?%E`@)_qxqG0 zsq1IFck2`H)=?Ya$i?uHGGxtULZp@l8TV(MsPi$1c%vGxbr2J`=4*5+h1_v zl9lL7p2fd*qa$BJcH~*~YhUvF7;8iQ_hOUUlK!`s7x4m>JooWa_}4G*;~tC`D0~XYsQ_A?+V0=gXRU! zcp-geZy=va-mY_NEC?=C+cZr)(}Z}dZ$|BWf2p<&;(gz=Yq9trm0{On@SkP3Y0dFJ zH{V9nEBQe|{C=qExRt}JLycwQ(6WMZwJvKxu76C^QCtd(D;wz%* zyZt;T?Pi(i3&CamU}|&~bc+3w02U1V%SbcdwBbN<(Fg~Wi2_9W?`8Uk@A-5$?(n1^ zf8tNXbt$bQ(~-D&t1ua1+!*|@24YueQc-ecmgJ!Ehxy%ckw^?SM7Q}mu3sZyp)fLl za~=AT!+bKcIK+yg!a?^Q!D7e=*kkl#N3c~1OIwdCzwhFeBb@11eSo`1c)3-O*F{f0 ziiwP0T1VNx@|OJcI{m3%xhEP{rCG=LSf3^9&{odb@P&1B^%x%(F%fY!Z)afkhH()Z z{wx}PJif=Ta-;E8e5-dxqfDKsZ8fIQmiqsy`8gK6;q5xAPICGSZf$nLx8J5|Cm<2Z z6H47Q^q}%=hZ}u)0#*7SrT)f;!KNiYhUhow^I%l*8y^mH-msG(8zxUD`QwpdUN%~l zfzT5k^(|=3*ZN7`mbufJll&2WX)R@+LhnAimL5OFyYW>X`kGVxPdCw@={yf(%8zSs zN}Jn8w(CFq!2=mzu!hcF;Dh5-pta9GFh-tK+e)J*_ zP2f8`=~|flsfCHwz&)L9;c~ce+W%v?Y>zKb$ZQAW+w@W^Qmw4H;c}-hs%-U+)`TAz z<9k&U*&^g%o)<-(BjlKNeo8~0f)-k`3ocLiv^RHdv(cDCUGWJ~v?xNh<8U>zn-=Pd zJq+OmY-xEgKCP#qg(gnkj8gYUYDxIE!aEyO9^$9%Wl;8st%3`_pg9~q$%B1%gf+xL zI6M<6ho?Oer3p2cfy+Izp0X_T-}*928YmW{MGQ3qzBZB$M9L$498p>^Onu@7M+#a~ zdX(JGA8}BHr`{1CRL|hmQF2R;CrZAIk`M7g(faCW*;kG)cSv>(S{UQehZ1+wXH1o> zZmb&xC*sp3@!(gvbw{-RqeG5y<9RmyW}KXj^|ej!lOQit`E0v>AVvNxj5{3q(!O#_ zm1Aga>n~@E2+IH&&(G$@=@NCZk^EhX!|wFsneMdXZE3D`;#ldKI$pZIr?kH&0Os$Q0v!1*Y1d+TKCGbf+8VhQ z#K>kYM;tx!lAIb~7zyXaX^xp=uDe6@Cgi2ihL_|-AGo)i-%>Jxt6S2Em*n?@8E!0z zYbPwfhcNyy;4|COhL`2XEC*2Dls6M7WQqKCOir?PZkMEO!2WO{!)OFDu}@r|1?-d-Wc@clDr-wHX4SIi)vm2wLI za0aEVl%M3wX9(-80etQZy1i05n($v#~EBYCT*A_QhTCVmDLPiq1YyfMOn=?-NMxUSna( z^V30W-T*(B;;EJuWm1=yJ08MW&%Ddc7&`<3SpWMOneWmGK3iq(3t+>PBs z)y497F~fn1utX>7^*%w1*rn$V2$LsKBuFlilaw$N1YQNvjuLrJ^qFn(;R=x4jvt(cJ4kYP__x#kov1z2=nueqZ3j-_S>UgMJJ(aL z)q*q5H8Om0A^O$5I4%2a4fr^d65f&{_*2v9jlMkGZ#-}|)_RSm$!~$bsNh?&O&r|e z&o>(wL~kvTq|T6;h4j~3@z7`k{Kmr}l8D|Z$45O2#ie*J%x z^0vH?AN-&G@!N77^AOj~(Gln7$I-cUat@#RKVzW;1-#z|IpEdRvX|kjfEKTp`(h2h zstlQW(XI7zh_IV0l}B0jAiFg)Ss0xMyNN!XpG+%D<%gL{wWTQX)>H~FL-+c9Dvc5Vdoh3}`*?e&o7Ur(i9%fQv`Q^jl&Oz|7!K>p!WO51=;Yo^ld4RVaKVk&Ag zX(x|d`s_*{`W{jI#i?|4gWQrmOHuF04|qO4)m&@NN6!%*i9JlOy#r$Jr5*3cD;ZR{ z8_`j)9^WVrXI^x4BWmDAS2oJ&)~i#X6+s_FZ-A4BO>!i!nW8_rNq!^D@5LvYZb)Iw zv_~H3Ipzr%DMLDB<+rBkd*moKf|l)(b-zvkHn{xyjn-V54-8-Z`%D}UpEYC==A zM<&o4`{V(hdnPpCy|zz|;-5{R;IHH_{9dWg5Nxb==TXi#a)`x6gXh=seZs!+Yg7sw z*stX;{ZjA9k9%(yOChqrPHaBgl^>*UfJysB3M-H1atmzX1I2fvVtmVb#y zNMOoFqni?B>E_Jhq)>KJh^ry7I45;sfT+JzAr*bNqbY_sA7!nZ zz<@6As^dQ}U9idFG`oJ=j{3OSD-i}z60Wo@BBot#l5Tz!d0@*S4NyY5yynq zvZMwWJv~J^%7sZ)Tjd!RMX$A0l9)f8Z?80`Gi{ZC2<2Xw0syyEk)j>ZO~Q<@y|o_F zPDy6`{lV0`z4A0)I+%90R}%UB!SqLarBlSygBx<@G~_Il>{!xtP+k&7MIDrTSvPWY zRPGV`la5LVyzT7hq{P$4j!H9F3GV2uM9@zil?;9>hr&B4Y5aT+4eO+I;>U96l}<{E zav%q5)y18a7IdbQ(v0uUp%EJ)EI!Gh=*~(CFVCR?ot1WcO%BcOjOMF7C5D%Er^m&ANq2qW zBE`*#Ccm9di<$0)w#JHwBGptqN)QO+o=4(Q=8Fun^3piesoU!Z)~Pp-c=rAO1bqeKN?-G z%=Im|hWQGkn85kqx3$z)zgez4#6!!o@=a&lQCs!#j?JmP0y;j&rj z&D$FPLDX-H5)oIJW!zkX>r(7y%U_j>xnU*3XRH+usKdvKf! z#CYY_LThxTM4XO(q_k#_>;L;m>BhurYpW8$eD!a(D$lzKBl9#GSfMOn{q@5YN*~5= zrsy#{l{^JHnGBiceW47Bgn$)KY{G;et^n#@G2cna=sPM5z>68I;{6#b>Ll)LZJ zKloB9@v=BXt7f>-@E??AW}w(jzxIQITVF;JLUjifKUF~=E~mgFN)G=em_{E_+8QzX z>qp@9!+&bH77N)oDkE8I4us;M^}sLaCS54`s1nCg=)R-MXz%cNF}j3ODzwa(_8wKn z$HoKNT9Q=16)@DE*ba!TfKh%`5rrKtt9c#pH%6& z!_y$N49IKVl}gWI{|iE4E*7Va0>PtzxFz7e0Kt!?;n_i?oqi{dTGuEs;pGAKl@yh* zqmtk%G{qh?zD8-0DGIRWH8&b}eoLz{39r8GUOGS9Xk2ikxmJwJZhaTReHq$M^x6Vp zybMVa1B3%5S4n#bMPF zup`7l9}Gp?XnpZ53SK`4&)wG5RVHAAR|DhJz8H66mp%Nfk_v;a{|738;7h!>x72<# zkbm1;KXg{{QS4(d6F`Ht**aEpTBQb@`L_<2c>cf;7%abOTc0F4l3I;Un1M1xLrN> zPi3MBaP3d!^H6a*ht6R|?+z-%D}k^&LuE>QsP3{78d&LoO=^`aX*1_JQ&@dUhMDrD zE2YGnlKxWKK$zrqp-28wLhW$L;r*{GJdDe7M+Qy>|56_I>m6fuEY~Q>qU5VegkQHi zqB~RDE6U*RP&ebbfu54K|3Nf4G{zNh8`hpnn?d*gS>E<5%ESJDJDQev-9af=m2m${ zcf_A}(6FmY4(fyL^t)G;(768#zp-N7_9DIUmvX=V`*)z*&gL4Jz2%g^m}e77kTsYEW;cupzOvA#;C#h zm@k?-pzN|M4A4hzDUr;#JWKM`*1Mu}ef34RmA`mjM2o|5Pqe*9*~z(1EcxQ#-J|R` zSGY=q-OG-;!o~iE!tk&woZ+v3$<#o(Z(&x2KnF!T);oSkJ_AXO;f&)oVcp(qAydfhZ@H!X}*V=>fbg(E3-)Z%hsipCO|eNU<4oVP}lmejTC(% zs9sW+MAAY}H7VxxBrOISS_#Hv8L$b%0xneu)621n5FR*|2&5l9)qXHKEeO&=*T|(3 z#EVp!MD4xQ`#ENwMP6#E*pGXuHkM5%z0~$X0qd=yxRoulkd6v1mmK z1^B7YC5;inX-9wtYAz-~0V@343Y8=T7*vu#7NU=C;^8=}mzj}8))5%{= z@IM^h^pxpaXbJq)PCj2EUV=@ASlfLXPQd}{s`x@HOZ?Zd9s@oL&nlR-3g>1d(vbi) zA?`(ButiEwWy0ak2XfT)^}FE73{@8jQ*m|1U~XOreHW;PQLjLCX#0ndqp`+gD8j;L zS)<&Bx>e-1iX}m{ncKn;aO8&4g+SHemwpG9Zn`5#z052|jvb+t?qvz4wjpYtu4}`Z zmREwX^;xN?1X?LE!@LPCm6+RC-T_Bp^nQri4tozQc4|V@8MeMcFx~27*wW|Wia{Vo z^sJE?sb>EUqgkQqeJ0;=K6)fnJ!GV<=|Q)^(m7^X%=7X)a`Z}kc*W??JK zsJ$D=69ACSV8&GtKuO_h41dr{1H;vv5F>Yizh*5+?@|LXY1FbHg7k3p75-^kx+g+? zyq)*19>sD|_mH6(Mjz<{8?MlMlMP22srXJ^nyl%gQ%kpu>RK8ORt}4eq!STpp5IfU zO&Rng-505D^Gm-Y8vC>;HP*@C2)ZXq?O}J^0TX3}1IwO#9*#i;-_}Q|ktP@RM5*tH zCKNhQdL~*;ZT?FLIv*BPqVs)^?+lE0yaHVsY?W$_wzfxURCPrOq~D{}=6pLGNZ7!W zEg{s&rVg&hwZx_-n0><@McZv^3%)RfPTACHwx>h^81$lmG5D@RYX=OHN)6=2QS^*m z4Ks5hu+py1bfSr-2#4x01Cot;I@Gq}?9ZWotW-)F?Wlc>n&&lCbcPFkYVX6pUL2$5 zG7AJ1oB<}1rMdcof+j1Z!scf63#lAmf_IqY9pe0-YMQH=!?a{LCV{(#Sm;YeNm_zy zU4mh5z?Rsxby3*B!$Lc&aKo? zk~?CxZ1ndt5MOtTJy2dpIuNgRO}rGUok?;lt?MSC3nTrqG}C}DxdR@^J13}Ve0d5@ z$G=aG2lVM(h46-#oYu4}K^+j?G)_x2%5yWz%Z#AbiE2yUy&XM}sJ@@rK)iNlgH&3F zH(j$){@I?=OtH*A^N8%s*NNIEsqMJbo<=9B<9y!48)7hg3I#(#W1G{lB=t#wb6_hq z+6Sg^#_MHB%ihsZf2NiCKJ&kb=L68jqbia$1qpL2T2Ok58uO2MdrO*v_)d4i=eN|3 z&oQlmr_VGMD0SG;K$;c`X=>nvHukF&^(j8qs;9SBy`UGcR>$cB+o~6ZSB#Q)>e*f` z7GM5!y1jar*Zt^Rd*1I;i{;Wqy-NpmJJu7T=iTh6F30u|b1ikkTzkaNCH8|1YnDns zeP1UP?|I}{wbD`2{?a)R*f`WcpDDNIC74nlYvMDra0s&oI|DEkgQeV2oS?Vwg6RdN zNJ+H4yE+4_oGv{u9bcr}9;zeeVw@({3X7*nMbq&>&=|;8@j59K)ZVPTt*rVi{;E>*SCHcvH~Bl6Y=wLj!CJOAtfvETZ!88q+MBwO(|tvkYF zpJ%0Go|j7Ps6Tz3rXGy`NIb?6P}UBwuHMEQkk-J}D{A8WN;AP_$M2rBJzWj&6zZj2 zLE5GI^k!!IVqt0-P^Kd9+4?jeGwmZUYL=k}bu$qCW&-{WpkG{o>pV@sx!&5(h&xmt z?_tJ&;!TeL!7Ky8Lt>>JP<9nSd+GtLP6TFJ7CP}bqzOuEdg7g7)WpbZ6?T^aWoHl% zzsHyUk_%P@xzg-ngXz)I=Yy{#5)TcG@elz0w*2mZL-asgb&#X^# zH}M%w5m`0{@m=fFTup(!(RW#x9Gr}&3t4K=BSygBbY$6JWD%|KPfkacB|FnlZ zr1$Bg!W=TwgJ#_gslkl@Fx@L#ohSe*m_DnYIzd?UR4}^GUlq1G_=+2#zK*X9N&j+y zdXQVHf!I+6)nbmimj{gXs3YOc9MkaT<4DQMWi)Gu`jVvLztI)H&P&9XJ1W}i@`GxWVpd0Ddfdb64{9Lh$TUMmK5v3lgql_g zWm&UP>PG(}H?c@+&;S*>(YK@2oqmtp5kH(t9#yCK#*010eObmc%w6!UH-8LbU2we8 zk=vR&k5-qNfeP$fMq|zLf~wybt%fu2UMdQL^232itSdRjsuKeRvOpjcE_1{qwE`i% zHCF9_?FW>Hc&x1kr>qr_k1lx$706gM!YUydQ$!&Jj#KA`cEwkQjOA;fbZO^v(hz%? z^kITXEgz=_#*43n5`WDj8;XnO9xD^_Bn`R~JmVRur8AFn86naT5vJeAsS!P};p}EG zY60FB?rf0)4N#b67@$EWX!d)(Y9C=C=khQM^hI^tvD7tC^ct_mD;)%~N#oUr%&*Gv zYIpO?cLKf)vIk92yF@ww=dg?YXq+Zo@_zm|_S3uW-r61U`dbs!D%Rz=j6;B1md*y( zC!1WiG52%Q2GkN@QhtD;I(Z+@spXbQ9}4>^qvoGHskVZ(3TpmB78KU*=d#vIL#m(; z6LDK6s_VI57;rak_#oOkS)J~4i;HN}Nc1wNw5QbB!cG3pr_=|b(y6eJZHgMkH*@Mb zMIGV4NH zZCDw?HQVl??F-a!dSSXcK6IWF!d1c?gvE0cl(9&)>+v(xIV=b_<5RRT$Zl=UYTsJ~ z05N@5%vA5eMC|pndM}g`87caxr`4C-`MlfupL5hy$dfEP&N5z9bNo--y4{3|W4Gv) z7uEiNs7j_2FA6b}Rh&W*^VA)dokD_O9dcrxn(Q}AWNcJ@IB1!#M)*y=BO035`D!=6 zJZCYks^DOEzMAgW|Bh&wM9f!Pi%s|fH4AEihZd+seikQ?i%~EHU8v6E)qm5%h3boZ z``_fhNPU&R_BWL+!d{~AZ~Ar-a>FabVl^ae=HItTJoxT@^63K(Zz~?{Gc5?F=$VVv z1G4wro3}~wGKKTgx}#9tz!+}9YwBgo4k4-Ro%AnXQS+D?s_00qiy%LdghAg?-&LeO z#^K}m)8%Ri|Dcw#NPQ(`N$qXQhr~7c)!ONjG`I|pc@_1>c)5ZXPsGdTVihz8Pn0iL zUlE7T%dzx=85l6d4FHB2H|svMT0)(Nx{=1AZePTUCzpV^G7Acfo6FS%aZl$pFbzuh z*VKEVLo9twjTKc8e-Ik4seSmB>w4D}>f?;ByiRYfR8#np>-zUAv6+CKMb0X9wSZft z#_?O%DEti-=ls`b#2ae3eDd0DTHTk2h5d>Tu^M5xDJsbR*$4-fC6VI|6)uO~P|ON=7W(jitFL)q{e|1hvntXJw-09? zsLxq0nK>bE(`of)HIsSj)tl8HxQ8{w#Augj`$uZ3_dS=u(RC(AVQ9TojrC3!Q6HF5 z9jW71^)&zcq8|ORI*j>mxF{OQeA}Qi-i2Rtkrr;l_N?$C{8B=50e!JV8$MD0@TkHw z8eqWO3`T1{Rc9b2my_)?HQDFt1>pBE@&A5-h9M5A#f%nxralXObUwW9f)NZL^M|+^ z2YI(c=0iqueb#ohJAbrNDh|-j-wQ<_W@hQ52(w-pP>;a8Gz1yrSw(7~crFB6UCbfn ziGJ={@tW?XP@O+52*H|uM6+XV}&|ce!9{NtDl?9S*CwAhM4k?Jz zcdDVj<=F)>#$In9(z6|5Glb#azSxR6 ziY>bQx%!q+-&R;@!)|OW3)<4L-RdSjG>n#fp~m=I!!kBoI z;{-p~svp^-#xrPqD-^BMV1p-US_PfP1H#?CtgS09SJC74slhTI6i(^iVAK9=xW4@x z6el7sf2X#!FtN3HHk^_w)k`5<>?U)=wWa8A3uUOJMEId_z5RamVP-KxGs20!SNofR zso`|)d-cI2BV|&!@y?*}Jt5ra=EnCJ)Wi@y!1ZW2O+27Jib_D+|KkDG-WMBA4{gLi zsVGUzD1c*f_*dvD<#Q!Z7%IaE6-I8^gQTK+@O^HUl#1ppl->!|cHw`N-A(kWLR<=@ z^dHpFS%q_PZBPsyA-OrWlCi*OK-j&sVjjLoICVb_ac0Ejn{h(C8DZn(Lmaq@2R_2e z0$q7=QY980W}ar6r|Vnt(FDate3cj02D8G9c~v+oG$J#^wL%l2S(WfIXpV}^3}Pc@ zris2%>&kSgy>od4r5{%NVqV3?two2`aQPE)&qUbLyr} zdzY2IO&2qtmT{rbZ`nY_zF;MZfVoHL!&B4Fp4zE z3ZjY&>Iax=yzDgnqFRG5SoM#(q~cT&#=oNVaDdX1&RtT+*ej($;aVmT%(F{HxLnhD zq(4qzp_+yEv{IT7PE-Db9tYD_OWO9QnhOjKtfjciILI)dhF?~@;L9FIbQz2NN@+|u z?YgY?Z3>U3!`sz=sjGxk`|2-_Up zMfY2J1uHn@)5Sl+N05*AvXOih{l*vP(pRwo9b}_ESJmEpl8u&JRlE9^M`&pnaL|XE zcqSmK65aU|w3Q zwhW(P({=#IBxiZ`>EO=+l*0>cWVr!Jkzu3GH&Fjc;WYe)I>OmY1ifNh1kq17)R}xL z2E$D-r%fC^b5ngBos3T0R5!&83)jRgj35*e*i7mq-ewZS>~s~hY4D}uWUBI+uuqN1XrqM{4;p^{>vky?w% zO-d?AZ^JcGR7zCJHK`>yR?_el6LlbbwTLi%ZLa!)=N9&?ii@;=__ z20qvg9By(yXCLRZ^>M44+_z6%FZIzNyd_~*#y85Se`Aol46Gc2YE72qAyNz0GgSWuv6Lp#W$B!7$Ju?})LWT;Hy>o{VR?XW9n zS~@$Hddq%#8@3!IgM{G5lVNl6&fOoNySxwD!aaPqmJWg9$b!8X^^F-M>PT$LcGGA2@<_kQAmxH z!M~6!67&6^YXxd}-GlH)5Y9j2PPFs|Ub$ROP~%zL9S?VreRX)D`C0813wW>qv!CBX z+1^#QhExv#rKo>fsA`%27`yt6Nfw;)NQZ9Xgs5m6Ec7@e-G`QdV9LJhiZO$SrtWu@ zrw)wiEn2ZaYeir66yiG6nVDz>{>02#@arAahpqL&T*#rg{mI`WuBhz7d$8j^a!5EB z_skvR4dD)V-?n01Ab2o_OE%lSx~E=AZ)21nn7be0kiE=pVfH}Q-&d}I_>yR0_kHDV z-jlz&_m3A>hOzLD@TnmokIs$Y7_eB0Ci;0Jd&{%Y9 zZ^zp1vOf%@5yZk?_LqC~UxM`Fi8OIk5(|GgtZI08<`93Ag=l05A^!5%&NTy^joZUH zM0>MdJ>&tpVQhL2d5Pe9q=!7x+Z$Y5-_t2Oe(NFc)JglVu;+TogNLFXeK45#H8|7Z z#bE^Rfue`IpovFdfBE;7d(LN(@gyDE;)N^hMlX3CuY4c2z#ykU;sr98SCqNElF#&S0atpz$k9A?&1LSuk z+%q0$mHXHd$EdoH2ex3-y`iHpTyW8OOfDbWZV21?_h=DjAEWj>;qm^SD8k6t+z6sy;aAkLqe+1e%@>f0^TOfqLzULw6q29dcZ?$~)Y7ZFP>- zL*zJ}jXT?t$B%iCoF|QgA1i(iDJ8iY+ewgxaze>2>=4zYdR*?aFdjsN2jJ~~XiY6V zJWPZa1gNju%hbY4oZ-Z(#(yT%=44bd!O5s!?paKybS*(G-hjw6sOy`{r`Z!)xYZe+ zXwBV+f~Fu`jhE54t?T=u@FMLnENDK5dusl2E8_6A#&r03KP24GS3R@>ukpV$MwY$@ zuLR4Ip=rReE{<=8%VQLq%FG$>{3s`Lwe@hR2We0LBTRJ2`v^lz*_|zg`(*vpn*TY{ z87^9?I)e09Tk5}BxM->Bh{XPC{GUhS{6=LYS_%mUsx9@smO!)=G8mw?)VCrW+J;WF zAPTw+U33NEs0a)R{402Tl5{zo^N)gisFm3v3f{!KUR2zs%jJFlp~e88`qmg^{DVOU zmBD5aRvlq^kkLjhtWI>vT9xgV^8W1LIQe&J z-$ci2VRA0aV_Xg@2y%>=ASX(;>P$Sqc^#&V8vzf#SmX$4*C*uz)iz$Ng=>9c8Km~f z0xewYlZ-)X{5fsm>fl99hp1gLQwy)PsiPET8GIxRqj!o%5Tln{5Y^E;QH0}t0w&(p z)e+%AYWNt0XTeW(gV7WcnnF_F0J202Uk1L;u!RUy(iGM(%~RyZaFD%qn8P+j z4%UU>0ZPtJ-&W_>G-By-$Ebuz1e`SuGh?JH7Y#fXv{`TID{<-I{v2bB3qfhuD+EIOXvAuV-KRY;A z4z=2Q8+xEIiMsuifLp=c`y>Am(+ib~m7~GS+(X^CI4{!Mg%@J1j+IkThj*QI=+T3H zA1gNs=?%CXXX_fTHdAUePxF{ScXVEs>@McLhUO{iiPpR@eeg7mZcbO299@Tf- zQHT4>eD%KplX_U7xX-N8%f~n#O+(jW&N&<#<+&IXR!4_)d6aSN^#Qp*Pvn=saNfa% ze@LlyxHyUy#ELRDcRDiV=LZjHxbwnklg2qVXUZ8g0qY`hHJbgD zE5qD9qhlDG{fe9nTE~Hc_V^%9>&@z4k*8t9dTR(9x>H^@p$HA7d;i>cUFN=rXmqd6 zhv4sXXv*ItbHAs1#^gBzbcQ*7bp3lu{>F#G4Zdqs`l)l{IR>0%mv+jd$Ch*RF+DsJ zrZ@B@He>GB9iC*(m^-;$n9eU_?gWG-qGlwKI416r>-GM20;xkC2EcvTBQjuwa{AfC zJlQwUuE`|@4=Bh)h=s2`2y@u-Zp&uMqpS3^g`CBP@z^*gblt!7j#8&WNI^?3Oz?h6Ev+^s*e zhpOfNeWAqj`TkQk-uB|n7F@&ZrPfdAj$PhmyQ^gj>v~x34ZRd8gdT1>T!mEp%``lP z8&bGxoOeoae0`7Yw#a_o-1PLv6>{hg+#2MWPh+`;AWQ_ zD9-cn|GjxKo|lg}bRUZbf5e^T1iM*S0Q*(c2Sw zs#pA>U>e{i?Cf#bhne4&`|6%&m)@7xNM}y72`A)hEbFM8AiZ#$Z8|CUV@5kRD6kx4 zm%DX6eO%ZJ&ZBaw(E;Up_BdN)m%rz6CLWUq>pUHgACo6bp0B_2Aj6&Su+zuov2rp7 z6M2!{J1%d;OHVeG$TM{?p`CqKj_8Sp3Hs;$aX@#d%h&hcrF@iN!BO*gls8K6_hb`J zaYw!<;|On_W4r@dbR2N(K^DE(i|@lc=B&!UPdZSQu{!AuJFmw4uHV>2$@yhJt>k#k z(vK(Q>-0&|bN`2BX>aGx9{~ z!uxDviM)hml*^4eJdS%-jts^ZwA7m51rnBH%ee!6Xbm=X}mlv>;NSO|YXQg~t^8BXwLFCKD?83+Le(A0E z9IGzMi*)?Siz?aHZ3N(-@I|v=G&}i;JYIOhL)raLpb@K- zx==Rpk~~RxGRCm&m$Yb>v5t$E~{6VE?I>CkK4= zH}*MvN{sJom3+#s>*#!G>O{Pbnu|i-?0&U8>;FIER&TcUvb?OD7c$Xm*jdd`)Q~#X zeJ*#<^;ZjM>5}_WC$R)+{ukiqOOVsgx_>T@_j~*B17>!(wZ-hs!)=RM)gYw6PSZU% z=mAI7ANYWy>bG_xJBN1a<+xBIFOrqss9oHIabb(o%b+`LX6WZ?THYpsL2qPl{w%VuLT!aPn*yA5g4&SI|1o1yS<#@A(EocU)A zVz;i#;qAj_-jJhljRAL@Ub`Vr?_B-nJ+=q~gUe%+fFHcc{<W*wm;8%#VITYJFL{XR zUxM}BnVGP#f+b9s;aB*Aqk>q`>XS3|r^M1iS*6?un?aCS)j1*7MohPCR2Q&emagmr!HAvb5a^E_LPBz1h9B~;dB0w|JbMH#vf~ZyYWd5@Ij?(}4zB?p3*H(r9Pxw= zoV|1xdJHRI@7$HAO8+WgckW^r*vLk<%H!}g*mbS)ApYj$Rylyb@`MAPN^6xL;d_8{ z=<-rJ9{XFKqx1V>?>&}`v#TOVHHo;O&tHAUEBonQ$7lDTnVEbL0k-bL5Z8F)Vh|bF zhdO194mao|rMuL+hxL?{Ri+zz_^5=DUd&E=M52McCgJ(;nmz2aqzsfk+QV*2$`ri8 zvaR|4`36hORMC9ja|spIMs5UWLreAGa$pa8R`@bW``vN9Vq3s7{2S-thc+lF5@bcV4%sFEgFuXb1Z>hPu^cV#FS zbKI2xg|8v}qgc1xl^&i7xM?qm_&c9<^-vU?BN_RftOd z>=(4?pY`G}D-c>WKQnZAD_4mR@%u1h8>f^15dmeRDA8+j=;)=9(krt2sPv$)E$UmPUXGgKsW@SQ8r)2@{12YP& z5s1T;CJ|>eSDL!9Iz%&j`LV_8KP zB!y8%^@jN7XiA!}Iyl=^C-HXe!J@h<-T#j$Tb)tz{_iMQZ#frR8BClp7+hYs)lZ~e zU#f0A8P(>-(@|}1Ea+`+Eb?vct}bpr7k5t=cOMsbzc#nc?lrK@WA_^3;vVke9_8X5 z>*Ai^;*M}}Pjzw6aB)B6;-1UhHfN3JyAT$+xRVdGwfW4+@@(~-0)>>JlCAmU3o{gW$Sd?b%9=0opjO0>P{p>XDsVPYIMddFH)zA z!ICMN5l|t85Yi%f!C9p@wsaybdan{sQfV;ObRuPL#^O$-(#^aJDP_(jUol?wB#laV zsVBCOu-1;G*u6mlp~`3l<7T53Eb=>AYdU$7ijKa8o}{j$Z;mIiIga#ER_NK&gOpLW zkieR*x_q6n&_`Dw8C$#PY9(V+7hS2|c(tpp)L_i;(bXDga~EB{n-MW<-Hf$ebudMh zbk&u}=3QO!c|{&xP0dZ<;GUst=%Op|2q&b@!&uox*XYrrBc$HwmDfdA+0ktG(baV{ z?gBSY}3NMyeX0#8O9A5CreVuPxTaTf8zm=%S2S9Z04w zvDt&v>&$i!(xOWvq)|$%@gNXN@;pejfk&~+#yWS>DEn8slRU+)Lr?=XBUOgG8Bz1x z&DkEr?rzTXAU1Zmj}jO)T{k(a}GWeq-)W$o59LfHfWI2ja>~?b}Std6}(FZ6Jx$i zN+e^ROs-1N2+1}Wb7YclFv4B!X3R#o8)O!hokt+e(~;mTvBv2XRI6GKrkl4y$N)S5~tPFIpVTxVv7&=nf z*BwGJAbba!&Czfwq{=~`^PqlfcE?b$hJjs%_){?Y*JxI$^R&H8uS-t$J zrK!svUA^qF8x!?9sHPE~!PH>z6K18a{I5urY}bc)4b` zGHLmmw3RDXE`P!`H`f^dsKWmdX}+ahss4|6F40g@*GLcQ=TZf=Zk8vOKe~3!`m`rD zw5y+1v7Na(6U;{+EmTH3Xq;lvG0S_3hhyM8Wr)ta%(8y@x(&ZAuwVju#l~tE1lzHt_&az2Mlpc5oHUCYWJ3BUR@RUfk^#;dAO&U3D_~4Dh2+Llf z1hCEXl|GJ3U}4Y^HapE1zfH<^{turGl&O)u{*%(1mEToHvZsDj zvR=KRcrfD~Wdj`kuQn^)ap_zMVGC}e&h|UX2*+my;ItQF@;DsfGJ*v=QJrXSp6g+mB6Z} zQBYu01`e-*m6?Rl2=LFfVQ+vV;T1w!fjL0qWQ8Oazz;0l2Y;kO8iD@6^n+0Qfz_~D z$Qsf*~;FH$swt#ebqD zx&MEJe4DYTZR$xObtD5w z`s>K9>57eH4}kE5fP!HCU`Dczq|LOU31P|3LO@}vjuZn^ z*6Bz&u;eKnspJ05s8KX(_Oy;916!U!JYdCk9Z8)9e-3K;kU}C~K>>lGI}r}71!e&A zu+ioNoA&BR1u(i;N5W^L%ickOY%%E5<2n)z40#t#1hl`0rU&}Jj~W8=%1}d~^s5vnHmX3r1^L|A>z>@#!NCL3< zHyyF1!BO~!j${KvTfh*Qgtr*jfk8TnGz0zd1PF~q26(rN6==Zw>mz|)c%^kBu)wv{3iL~-?vqX$>2=5{he_)ocWFwJq6ky3p1~&JQNIuXX z529BCqx+x$z)HL%({~gJhoslO@su3|lP` z^FlP~Rxkh>w&U4%V8srJ)benAX|M%Y|FT597GWKEMIvFqj9q9cpy5^I18h7fkxXE| z%`TAwIEoz-DFZf?qQpS|6B02zjD_hWN)EJ_AwwWNEs+FZ9!`8Rfbr+hVnE*t2_qeY z?gNR`08=mGadlwQWi)vLTHrH@Sb#xaprwFeUxFXdR&fm_f}^G$41gK8BvJuPg8jDv z7<~s#zgQuyz%XEjK~IW+UU+e1Gq9qAo&+wzG<*v$as+0)ttU~yNV}fI1H+H$Niwh& zm<23*2kC)c$01@a!Thg-qZ$DfC3?~b^nX`R=u)%<&kK3?+9{U`LK7?^WPPpW_gXYi#KVCgwMX$3}C=!qo}1-hUoF~HVJJxNToA>d;@ zNkKs26$C5;;xpB$z~JxoBmE z24Z}K4{8Ik0BiafNC?m}&_JSqWSD^@0I$w8kW?EShKCHe7J|NsF_2PV{u~3T1t!lm zkOpA+5-*5sRvqGAbKaE;CKk$49vP?Ai==ER%8tH zmE1@ou-M>6(t!mYZp4-YhtcRp3W4>&5+L<*BbC5lZ#U8ejPLA5e3zqZ0^A6sEmGCb zjidp62e^?OVDvzw2iga_kqThhP&d*FtRC)0%qy^Yjc_AYVDv~g5(#V?KEo0nl zBnu9&ac(3Zm>uRuih;fp+(`8o02WrE1%RcO+(_W#sCl&;2?Yjz zj*Nj#SHKtOW%~+!0Y@<~6Ic)ejSW~bQYLm_%4nHX00a7SPxqG_;&&cp#b&j>^Fp zh-=siZ~B>yi(x2yEEmH{fLsh~1adJfl9E_1hGhd)F^nS@!`w+M7sHZ(Tnx(xaxttK z$i=WQ5AaEc@Ir_b3e55#`aED2F#IVIo&@yoKy3Q_O^{DJ5WW9qFamPZ z$mO?YAinEO5;~GtF1{54x%hS!$i=r1PZG<;w=KX%Aj~VV=@8$Holqc%Z*f2_zGVZs z_*M_(;#-iHjl_n-k?uwGk?%ol0@l7y2##F!T&}C}21Ceomd+%W%XJw*F4xrpxm*`) zBC$~r>yi<_8klZI%Rs!#HxWG-^XlQ}VqRny603@Nz~XCYVbHxG?pbYSqUUm-xhsj~ za$gFN%Y7BVM#z2sJ|vdQeJMaL_Z9e(*vJMHz=!BFenky@iJr@W1%4#9;CE!yjp&p9 zAS4qQ*bF|vMxeou=((I2)Puw}{Dlg2M>@!hwp0Xgfw2}?1xy5i3yzkaC@}=bEFhN~ z>wsKt4DE%cq!3aN565++1z6$^^MXIoheMuB1#-DE2l2RE*#zWrWsHTya=FqDZ1mQV zA|Ai9&PKd?qlOSPYZ1T&%{2JApjipzf~KVpx(I@1Iaj@0)d`pljP4AKrZ2jpKZG1$+5pIh7>r#0B>m7*1BJhIpbY{d7~$pqBoCMeuFyy^{M9&3R5=dgX;2I6g8v$tw;aq^-1wR*H>w#Q=4I6-hO@KTI>IKD`{H6&Q3DO%H4Y zHUjB+)FguF6Du%CfoUH=7XTJqKuv)aABqB(eT2aZKi3)3Ci8^`=_Vunx5yZNt~-QA zl31=gWCLS+!C)#{ z09XO6_yvOt$d!#u(7Ccv1?0+xc{=$00p$Z2_NORl$X_Vg94S3)c^F^!;v)B(8?5*1Bi%YoT5v2;QiDT2S5Lb;fQbWloSfLu9godw1n zptL-M1r5r{E?|l$bO+1^Bb1Z^#N*0JBf^7B&!xxmM)A5d0QFDFNC-6Hs$Fl9mWY zWlPbNi?Dzs;!OaHkijyP_+d;RU<$AdS`yEYYfA}>(Z@-`UkR*xnCQt0#81F_0Oaww zHdTsvmQ~P}5YDwKvIGTPuhMN&AslH-uq37-Ltw%NXe~?8#~THMpma19{9FwSOvG5& z4z&%))v(fK7@RMn&l9nN0;8899@H}9BiNpymL&nXT2=$(YFWsmNDs9v8<@kuKgmY) z=GP<=pM(teqKSby2he28F%1tw?OKi{7i!y8AXnS!S77^u+Gc$WgY*P40CKgh5XjZG zR$$U8wBQO%FQ{*k$s{(kTq1e!b2Tm>ey+x~0=XKOU|Wfm=mQK6AlKtUR)GQZxRTW< zA=l$l(Bz+^X;-01Yv5mv(f$Q8L^#*$${xq|{S6e*$FTxJy^8^IH7_a^UH3i4$Qm>` z)V(wySNjSP9`ggz!CwrtHNz45BOK?tmg|w}z;H=VEKi^U&?l?m=lWz|8oIE99`hfL za3d5)L?{O~reSFusaG@18Ko!D8;HIvRQPLw72H1tdLA%ptO!pB#%#nkJP!IHFe3~Z z0h7k-iPw{eHvx3uu5djm02(GkUj)WP+MsZz6Mg;^!KeV334coz^gdurw4NBBBKrDS zCdB3{BAD5UUL%*9uBfvvy>VD@~}Y!g<_g{TlPY!Na9niuOyCC5kf#CJ19FJKI? z!Ujhc9IcP)Ne$2|392@*EEyW`79?0DGPJBlJoqcNfDzFD8Pounvt3U@pGL;nP+)+*+5&$8zMp-un7UQ2oW$Vf`Mtkd|)ZC-5uNsOIojx6v&MXEkJH#h%dz8f{mdR$ZZTQ zKyG6Qe*?1yHik&><+g^5H*A=PFfvqwz>N*TZ$e>!u^|V@jSWpeD~t_WkboNjDRHvyZ0X)sdoig05^HR#dhdJ<&Y2GIx( zPACJW!0&Zd_yd9Y@Mi;Sc)WAYjDUefTp`gDb0%a&U?h-RJyH=K@_`!9kS0*d0`3Bx zTSM%i`+f)`2K-xqHvfMSj3{IbOa=0SaB~Sggq7_h)Bxe!Y7!5BF_6#}iiMd&(^e{G+ zZ!m9unbs#9Zmi`7MvTRAlz&dk9gc{Qx4>2o4{gh-!R+c0J+(w1<1`d ziEm*OyNM=8`tT+c92oi+=6@A;+|?8R7l6b-Qh@$$22uv(cAiQkh}@u25G z&|C;QuojpN%w7aKF#2K8bJ5QUC6i$oLh+Uo8q&^ti!Bk`Unk zw1MOUt8 z3l;iEgl7U1;I9T|18b@bq!k$QsZB)SX0}8yF8abi!v0P4maou9z@V!JQUm1Xw{p+} zzX$zQY$QK|4)p!gKpKIyf1wK*(!o4e1LS5p%W;eknCTLM+)P&lJ-b0CD56l5_ zdtfav!-NY8py!)a#s+IwH`2`0b#o)puMvHsABydF|8WCjH6k0S=zbgV= z!f~=2F%+O{rovDO430v2tbbBG9EAwr7SIADY?&b#M@6fsT10)zASc2inhxX^(OMw4 zh=!iRV2Z<-K>FHwFum>r9RGZ~AnjR+9L?Abz z<^j10wHC-tsKIAo6UacuK>s4apy?2r5PskHUU0J$mF>pU2J023_yK^H_kZkn}T zK-U3Nf!s7}2XfPF6Ofx`qdvqAc@gyUSa_;1nBnIp+9n`3(MDB5cDRfhmLmeU)#f3f zyapLoU;zS#11(>GF)#_(04xGpKETQdi~=@&3C6%8*m!x(ih;H8*E{{(_S*!$USFZB zKEgBxrUT92sPPR6c;_Ig`3QsNnqZI(q#tAYe1{Bxl|at87MKoyXdMa!%({;7i)gtU zf}RYtz+VE40g@j@xEYuSzx6j11eo+EjM7z@C4ULJtpJW31jPMM1cbHVJOKV0AkR4X zHt-V^1Q-r%y^DeX6IxLaVEEslUqaX1L&iYg`xwMPFP%*2r^r~6Nj$Jz47}@Y$Nj)o?tdTge}EsD08BrDD|x`clPDN4z6^YU zyG|kAkJyY(BOcIfD;F79f!PQ!oE84abC^Eepr-+&{kV*eF6xI_QGu4~k1hd*0c(LN zz`_sE6~NF7m>nS~0I(RwNq%-@9ghX)GZY-i&yLI!u+V*r799)yuki-@Y#jQgK_)rj zsQJ%`IECm7fK|YHU@I{2CQ3dPqaK(5v;(u_P~cmlz-7S11dNSFndAXmfR(`HUr_TU z7*oKsrRb_(G2K@|mi#Z`ujcmOCd^AH7bUG2B+sG7f2#}){8S5%UB#CB;uw_>13%r0 zhrhI!@LvT+LugH~03lq)_r}p3M6a?wf}RzCGsArJHBQ5df&5e~9dZUg74yaZpV1HT z_h9}P!@)D)$7FTbew%=5hBz%t$2J)}Q1wf8fre&a^f`3JAeq2G_ z&IEx5oU-xo5P?#t)6Y-e8h(WMJ_K~;J(&7gpKc<=%gfk{;Lwd&@R#)d|L*f&wrV&f zgxHgpK>Ycih_R2bpa9}T$0 z9vcFF*3*JeOr3-)H(9Ttv_JcG2<>S~zaXgLYE4j#TPk&mDe)6Q*rgFp-W0j*9g5s` z)d*@Lp6=s6y3NV--cT^j|5i|8cofuFHSH`@-gklkqpl!yy2)M+M%|*W3xZiAeEu{0 zDHx@1y&(uO8sX)i+5N?+^x9!4Mq|C8rmHeOiZSzN_URVX?b0whR$ue;|5%6Nbh^F) zFKX|eMaQt5;nbk7`{jSE(^Iq$dpe7nSk-W9vVL^a**oDVmIZ&o4T3Qa2Gt*(*uZA5 zqdv@U1obn;{Vb^U8nr_MJ9>$BXE$%t&fSv`T8zIYXRKhYM?U|Fy*z@>Gu7M_$rH8Y zJAPtkKBFU9Pza@_@tAKmc-`))ZMEM@80 zlAmeM?vV%#Lm7fYM8vjkQhsEg#-d5XM+!n)7k&DJXi}U-kuWE*8dpI1j~@Ji&5lEp zmPE8;H}OZ&q#d8xew`#LFi60=p|5iGy^fpz+V_F(pCDoddT7Oc4Y``~d> z+$U_8$E_bk9wBHD!;E%$9CsEwg}0WIXxF9yT7@rJlE0p%hEQLh3Pg&Z+m8Jdrt>{o=ZOfr^lZXGmH;@+R#9D{YUKDizBwFgu`pDnyYQ$>sUM%Lj$I{_aV;UdX4@ps* zSH5%Q`fAquaZ0SZc=g}}a-W2krphjxcC$F>nVHka_PYHrS zYsQJ!*{3@90Jdp7?PDt1B&abO^==)XRZ~m_&gyt+gyVH0*}w@%7QaO#YZOHxbZs45 zIswIKb`ol}Vhjbp33LuiokXeBoWV9tqBA_=kSqm%SD$0gh2wM0x39FD?0L@!{=2l? zyMM>-PQs?ryoCBo6${xjtLShRHW7m)MEv^dXk`9yQ2z1k~iSO;Zqo=Ln&MSYBrlQ|NFx5Il{09?+8EkKe;O z&!EGV0=TQ*XkkY;)4nWq1~^qCBU9qb(jPd5G<9D+l%*q=LoN;|S4@zhhU0DF0ZTtw#heK9Kp3F8zYtkD~tU$;FUKNU@;ed{Iz` zej$4K(qi;--P?kirq$$D4Hq+KnVRi_5UDXeSi_bs!K%`5tX+!LYKkc=_zX4p)F8UK zM8q&_N&DBZ|Ncn3vZrEbCl>WQH8ab8O2=AHigh zy&Z!Q(mYG_a24A+1A?t}88yp%&SyQuCM=_)*p??T&i+%`u8{*zh{9HYKmXB*pRrDJ zFdc@3L-ggHl!CtkXRNk$%JdntO~XvSdRine)!O8z%k0zLNdDtA^g?90poVC@aQrg! ziK64XbES!|j+S#G0uF!GAAR{UTly6pV3066S$PL{{{>};)>`4rMa052+soQ$4tH%> z4=LT)E8N+zk@y|~;CVc&})x}Ei2OS`dtiPWJx33J{4 z4VyX}Ly=EwE?1DNLaOGkp(8EuwCP*kydfI!7y7MWSjoJHLwYS4bnVkI~Q)BW=x znAZIvG?0ItYL{cQlV{tieyfswcLh1_osS&Lei6JXQ8xag$18=b-ZYy1(^d+DjdS`B+y< zov{kESl?aX`+Ik`BAxc>o`%q7zWNviFN?O|u?uYPBXqIYWw@>siEj`W`2*-sqP7#o$=Y$i*x{cEb%O2Iep6dK2`;_{}NG33;y!VB5{Hd9{lLT=ea67r)Q2u z5R$Z6vHtvnR!wB$}U_gGp0vm4rL_xi(QSYDQO@ZP1 z7^q~5pxQO6N0-2r5oAMA_D=X$P>dWIE0I+c9TVqCm9ZFUKlM%$0xsqa6@E z1buTZ8M{WPU-?qE$J_)Dca7m_AFnF@xEnF ztsUS@tM&Hev+UwZt}q2Tv(%DxILoCwE1R~8j+AQRx$ZGRDjLF0a|{~F?s2paWfN8d zt-)pU`R70kX~4K*=!81qbldYCg@a5b~*t6>RCOrd7?v=JgKh=-Y3ZVENIr-q0y zs|Y*G!xBb|uw)^){h302r0VI+^Ks|{ecy7nXB^tjg1=B_v0-rT~^#~ov5B6q8Dk))_14ywq&dm*4cs(s5R1=Q*6f?I!9`V zVb|8su~O0;=C>BZJv5Hv5SFnP3w=}^djTFPA&#Bkm>S1!a?C`eRA62lo53+?KHHRv z#3l3DP54<|DiX&m;GRj=>3H%$oebfqodti!7*Q53hVdWmev;41VWvDMp-q*!b%Nbm zhn{q-!-Bnqe^L#M@;LQWH|aREUjBR$%U^5Bi6_Lk z-SY&jmZ=K_wMC;UC)mX&Ae31awj*45pA&|u+EMi)LCn)q9aM>fS@?RWy@thX$$HvH z3VMt^yB=HOvNxR#5s89Y@RzkjByXEa-<7ieu1BURO9jDS)4C3pve9W6>sMC@LX%e2 zou%yMG^EIUOb|-7k}NG{x3bZ6cR_V8TP3J5d_elJm<=?*`hKCaG)d0VY)KZ8+T@0l z4pnYY1n z3Y=xpR=>nF!PKIaWp4@ZGH9Mp!5|c}K~TB=$A9!uK~;BS>ZK|<*~l*H z8TR&OI>tI>kFy%d2(;iYaEnOP)}&|N;kJf_ruwG^q0L^f{T*R1==lom=~IuSWi}C` zZ4HlohaW4$>pvai9Wl~Gw+TX)wkw`LCYHW?Ph%x6 zp2~(lLx;OJy(D6#h}HC$rBH(>e?q-GsK-USc#U3WZ$CqqNF^^bPaD>5|2IX7NTxf> z*KQl_WqoV6vk6jo0{qpyEF!fXx9qUeg>^Fv+Zo@w^(;aWblIT z6x1fo!rxs@JD3$^&_Gj7p`d1Iqu{PxST>}sSkVKWg$p;J5ctt=?Ckz;77?W>LCa&4E@Bq-dzSXKUT4l~C4!X&e~E`gq_z(H=_p(K zES+P@ep?XQ?D0E~vK`y7SnIYyyofp`sLfiL#~tNm?#UKzqrFUx?+7Zl2=O0P)U+$z zo8J|L_I<;)jiYAk5C3)+E*fbp_-l1WZ(FHHzby==J2J7GJ*7q0CR_4*f_n>+@*n-~ zEwN<(o{5GuI|Q{tEAsKT#QD~Ye_=mMeV_SdVSi6P!Dn)SIL~VR7nIX_r>vyu_RmpY zDLtG`cn%v`X*gTM(SC~Ud5+Gpj^F95K|Hdz@G>|vZQHx_#r$;3j}6{VhvF1c6sgT1 z;yA+AZpVPBI3)-c%6XtBJB|od%{{K!C6^ig`Vc zeH8@N3JN2MztmjGRy<=XhO9pd)F zWm5fBp8Hf5{5DLOe4#LZD;B})FFAR~IC<~-TCmuqwLB|gYj;4(sJSW#*&5-|B5q9% zU_b7FwUJ&E)GgX53MdlOJtCWqGMVcH)uK_qJIKow$c|^@Y@p`4pk`{E4;Y8u8Gcns&K?kxcFVenJGK7+-yMpSa?bPGm5J#{lUq;6H${lqTDdakXmG#b{ z-K9VeHX#RV^1IJFGvamu3;tqsB665k#o2}2Fx;1w=fM6OEeUFfMjfG2ec10gw5usx zFR0-f)yGL4p3A8QLFHl)|Ixb#*u%LHC&JtWfp1OxN6#N%$8#}WqhTSZjP(5w+g>=%Qn^DgWiwIQn1uTScBhaWbKcW>w>q8GF4Sy(%7?xKEDUWm(a z!Vj6woV6`7w5v$bCY*g*AdVAW`Zq>vOMB{*52yoK#Uz*q|J>%}s7d->&N6su&88Fx z{pQJ6QNqlgBEL|!Oz-Z)>|93r`c>+u-_rXIHxb2KzkRk{<4`9<+};)4r{C*T9T;}O zgua5|10#hmGv-mF6w{CSyYrBEmy;IBdS^k>YR;qn z9(jQxemss}n`u85{vT>_FBl{OBiXvWoXLN{q<9e9{U1pFb28c$*wD*aB(1;)^4b0W zpf^jcg0MwY1nXnISXMXerlYJ|aZOa!Ahdm?X`qN+s;w0P`P@=E$31Im zh9xp=I9v4^G`ym4cHuQTRi8M+*`6QZQEQd0wz&Ha7pWVxF|}j2XwP@@v3wPd7F4@d z#-+Qt?Cs0$=fi|<3>DPKwuN9f8~QrtSm-1{$kFON+sX9p*SWqtMNmt$noQo!zT?TN zrU^n@i}c#v)*=BcZ4WAz5XD~E1F@%S9s7L`-6-X+XRG$oQTnK~J8bh5I$fN3+0)ox zd$AGLZD6AcfT0`NMxguEjUt13VWa)30BcjmlkBeoEQVX2VpI14^Eb0s_aRNu7WU;n zI#()unho5K(>VKNyz&BF^-94W|pXgD^OjUlipn>L7-EViBx9=~vjRMQDxauh`8Z2n&&4 zF~37JLQ46HEjfgOrhm=eK1Ap0>%P9jj{ZT%$b5Xoe8VCR(;@B^-w2L@T!`~$|2|B+ zyJysiuplAAS06^JWczor{#nq9g~@l|9UPB*5=u=TeB0m>rtv0w;t2XP`KE}N z$C-3vpB+JU8gH^YM_{`OZxpm_L3^SYw9H1fyBHZ1{UT`bEcXI7n|sByvwN*GERJ1v zb2qV|x2Rb%|H=zAgr&X(86^Byw&^XjTMKs0x9AYPSCcxYaKQ66s9SzxW8X$Yl>N?L zcpF(X{4TP{6m|Icl4~6TG1>h8V4aVm4x!B=Vm;Fp_S8rI?+!a@r{ncCaNOmNq!u;#czqKb zn~xzR<2K@Ohw%>L9HUbPhS0m}c3tG0;Uv=2A{BV5hf3)bs*jW2OvGr&d52mCCc2A6 zToF-!k)B>swn)@~L~)%3J<3f@^y+bH@rd>jVJ#wz#qhvpe-TKWfdxFUu=hU$n|NSc zKM`1Oa4y6p2y7TA0>hoja}ekrw^#%g34`X163m~BrOfYL%$3AMHuhcgQtC4H!n-hD zrmtXkIQp()tKLK37Cp`m1N8-K?usLdjt(plB#jMpVDqToAULOsA@zy_L(067op2xr z-w0K7RiZp`oU!4qdfcyM!IQF4csf?X)3i}=C>LAum!;V2QlE6jj^giQ(>z)5q^I9y z6Iaub>M=?s0vcTds24P!r(9x0A)v+?pjzOw5D>NLA345yg8I2v{xj@L9+v0S5L)>v z)s1yNN%5_+&1~RF+>N=KA$X)wwq!W$)&(aqS$&^pCr+X%t9CGtGBf~vjYX8JSxnDG^R=M=`Z{Rfda zn*CM;Ew-+i8a+}l!lKN$Z}0;fewwcFNNf;s5+$~0IQHoePNR#Oo7j!hbiQP6W@FEw z1MB{}%Ql~(%iYud7O_*IoqeW_hO~xG#t;1vpeM| zS@c*o_AIcb6Weqa3!Yb3cK9q-$F!~@O^n3Wa9g_XIV|~GeA(D@+?L)`5YsT)@gy zKc-cjE%POr_Q0XuME3gyEN4*>B8ybk`w*1*Sszl9R5_VF@*&!gMzU8vM4RSEvd=z5 zvGQgzk4l86g|e|6GiR|?9PP8%?nXD!iYpTSstC`C@J_3*QST^G$2m-!w z?C?jZe#LwdH;=uz6iqeoV>DG*Je%<`_|!ZqXm)mXD~t|BAEV2{ma~sRlM+-M!h$bi z5ieiP#$E*TstUI0A{3*A5497*(oc$YH%1d@SEmS*L6<6+4ARR4HAABgbyAmeYU3$E zEfh;8q5oYiY;*5a!K7DkT2NCps$(@jBpPgLaT4k^0$a^`eFF1Y_8F0ai`x80A6w1V zeu5MQPC~T^Cv?PWcJvdd!CvJeMH{RCu40`ofw0R-;F~u8(Icza+Dl+n>?Bl)a6-4Q z;u6_NQ}Ee#nLmsapI|Tb{}hT_k(2uW@%At9UC;mjKmOWUwbx#&R_m~8)jCfnJG^$% zX`Po2lCWyk&JEEdOyV_)hA_l)2#dT8VMrT=#UvF%n51(WCPQV?;dj43Z@0(jWqs#! zx%@BxN0(QRUGMk%<9vKRU(eU$nP-CawY5F18J|i~w^Lhbv?;+-+ zM*9@C&9;knGqrU_JCoXM)uz6Wuqj5{;R<}y_V#xF4#DA-(B>QM?>W$(+Aep4iZ(&J z!)V{nv08m0SFkfblW$^@H$%I|XssM&9-#<8nTc-MInjkTMCe@U=4Z*5Su)aCk zcpa=^pUX9B$S2TN8EpqU($3cHpZoUl&wX9JVuG!Rw_cIw zMT3L5nXA|Sk!9`CVAWJ)nql=!mi5Y4{ug(sl7meT{)EKpl^5B{OM~}v|5qQ~UzwVV zN%pP%5|?biT3}^x%Z5dr|8tp^=W8i;ZCfaUjACY{-ng0+T+H1{eTY_>*6=E=s9p#$ z(Od|@`(;V}^A`6?-G0s4|NF8T#PLq~Mf^P}F~EwI^NgLW~I>FxgA- zqOBNe-)Aq9y~W9kU{F8oZ%nu5@04y4dNCA5D5t}JoP<#0RJ8t)C9okzF!0l8!-Jf8U@(8YauA?_>rEIu32J=@AD~^-lHB;E+F{C^m{$ zQmt3Mlhl&yps4RAb5pHWyCp;&_XjJ?#pwAG)ovNOqa9c@>hFf1nPWY-+dnI~qA3(L zCgV@dvAXS%$+D&y6!pXTx;fUIJ(9-4=1>%y5Ycn2S5%P{07baT?jN(QGkYZQaF>_j zYg-Z7pm{*!y%$aSSzfan3 zX*b4as-UwZHd6LB`UJQ2;y$_Mm)9L8^>^a-%(C|E^N(qh*#nA96ZS>x^sn-j!PxyW zvE=oJa;3@7&9kf<_e+X_%*sKNm2tDIPxng+4)#Ha`av5!ODiPQiasEdaOru_ZZN?P zq*!wf$emJmKPW0pLhDm3OBEaXLs4HN&!kwNsv>+K6iZFMm!x1u9CT1JUUfdSAtt`d zC82|ozmfg11uq;1qj@ILuV*6es}D)sYda%EeU*t;YNk_H$%!s^b+TRDo`@LoOfv7z)Mp+h z1y_%PqW+7&>tumiDe0%iVVVT@BCqi4lZZDa^(SBG)d*~!)198fenlr2p)zVA@s2CCk zjsM^o)`Yv8$_4`S-v3V~cWRZ1k3ujyFmY@93 z_f09aUjE5{q%)!;y2k)~ht{G-w%wVfR*xFl;!cxydDh5x@plbmQIaHuF!=<&iU?~= zU41=WXUneEp&I}5oh!?s4YM|mm#-wo{OsS&x%3^#=0Wzb%HlUd7J;Nc`&pg_@sjx* zk?h2G&@1FvYvK{vY1dU)_Z{&cWIuFXD9QV6RF3rx+GuS$BA00K8?7Tpe~-V*tl>V+&em}W7VQ5T@>xH2*I%Z4v0m1MT7PG7 z9<_U=Uex*DV{0YPwYpP#9bxMioSB#DgE&2{Ewyr&G-NHbYY!xBe>g?sB$4t}&T=seW-P3*CBzEi#HY z3HzJ$|AKd+2s4Ubrs+H(k1G8p{Xew=+Lb1!Wz(!*ev|REfr=axY{@k1{NMe@`v$#d zE&5%)T?qWZdii&`G)nxyI`X?*qg8((uMdyG^rE!BkwElP0zpHcm zhtU0fHQ&~^=0ofFQMr8e+iDFvCKv1*zO)`W=AZ4m;v4JqF^R8eC&H{nZ@T!nTp*wP z*1G1n=*o9NS7fD02eoz`mv1(MzJtt-LD9m`8EkhdJ)tLXkJa@L3FqDen}c|0_J%*? zp5$iAY9QOBvdq1(qpW?Ml+&@#8e1p%E8K6rTqn0XrX8?O*U9x}(Lvaj=rv`Sb<3ar zxRGN&dB0l5s%!fcvf07|3`m6tL88N2;YOptga{hXE&*;J85}N%B{WXKTlfk zp7fv8WaSyTpK!{5l5dIJyE`R!x#l&oJ~<_WYFZ0iCrr_@cd*>2<+^%a3v2Rez4mTl z-Fn)8sxze(Y>IKG>iB6XOKmeuGNrgj6m>@K5#=<;sLns5*Uzo3yU$1@JK9-qosmNH zYHyu5BMBC^M`U?cT7iFbi_Ox>Hd7R#cg{l}e%9HiSDGwgXMg3ve6}^6^4qZw|Kc1P zytXBxtM9B&jn#23KPL==qTB?SKURBjXX|MnXQ$v5t)Z=71qYASr+laTR<^hL`8s0* zazkJc6o}t|J?QJ~8W7P7!fgQ%?iZo&nn9Lt6X#{VZnrg~iF2$oISxigag%3T6KAi0 zlkt#E^s$Z{mzynNeoh%07g+uLoWp!~4YscIbH+MDhQlb?y7z?43!nKpyEO?LaSC^b z+BJ3d_nk7r8rjr2*|~NkEGzMNerZ!@h;QO3YfDpStZ%_6%eR?xtZ%_+>%wNjjxpBl z%8s$t7GY=Gu?RcBTIKKTZ4GMf?BQFRWKC@@Htq@5W9sjiXzg$A%x)4k<&^cxPcpS# zo@$-ccVw_b2c%;A?K=I#1zZ#T<7Kyp=nxz!^; zay%~?x+&VtJ6kIPoT0vpldac8=evBmVUFSQn^zjUc3udJ6I zz0~?#{a$xizO9^toD1(jK1y+;a$+lITjx>ABCJ)dob9YzTRA)V*4$}5)=JW;U1ohQ z;e1aPSiV8xhuv*O1v$s}dR2ZeZTI96Jtg~}PLFR^ zr^hwhE*G92$E;3IO;%UF3jX#I`1VUIwLe<4Rx1@1uN`$Oq}M zHQoVUl2uIuc*|cshx|ghI@Th1+kfciaP(|IF6S6IdezI@IUFXZCuDAC!d8sn*wa?wQ22OW&Zfc)`j6d}-T?hWG8*Bbd;Gx5gb5-1MKUAnG$N7?~ zUV03-T3_o7_O#bOy-Z?6rp4HJ9f~MduD0{GOBSgel~?%LBG>TU79u?FT{#{lONX$X z@AdMU0d?Ak)b+j|0eS-+_mg{&U-i;|Mea-eDKCAG8xUW2>JKxcN#u*=H5XFp4u`km zYU!s@4agUXyh8)>u_D(eq9dB3vhS3?)%_&tYk!Z(Lq<&JDWlyDD8IweTG~^8**&Nk zB3P!O#r-88Q90I8o~J@_b0k5H*jsLf%lXY4&PWk6qG8o}*3s}@u;W7UyUE8}K3Zg2 z^3nc?I8**sw^MSbedu}0Z?&aT5SdD}wBb(JoA_6WOs59QJr1KtmH=|aW)$`E_9E9l z>mAW1k@c02*3LiODwZ&e!i{8OclJ1uo@T0S9dnw>fDijQ9NO_jZoQu59Ox-H4{`87 z@_&tVo=1Mpk=P*sRiRa^?sM(^cz|@%6oB_N&L5+7)D-N^*Ag@ThY~=FP~eR;0Q+$tJ7I z8qp`ZP-kan#o>69^0RUx@plch?LCf*?d0&YIN6;VMZNrXk?F{1fO@%(T(#exkBooB z4DO*ng$tI>Z|aaeS z*m)CC`xYpgS)Yhl@>7n}S z^o)Fp^jLj$dVD@a9z9uKot~htuGd{Cx9QQtTBCHj-BH&~imf&EDD8CHs%{->VV)n%HaP7_JcSL}>(=O&`%t2u^0&HTG8)9;Sk;K$*%ldL z2ei-p4VQQtlI!Yt8}09szcqb_xl;P4LgnU4$y;u&l)UBUO37Ppu9Upxa-rn0Hvz78 zD1rAj$y;u=Lyyw_7R{x&j#5?HDfJ}=>VoY5|6aHBtqkh^t+&fB&o!OX05SdlO8>9U zD(|JSM?mQV&E@T;T|C~?u};P3$;Vr+C2!V%Tz94o$-7B9TF2h;^bxu4uqqy~``|-g z`gimswMT2Di(K6*`NYb{TmHDnbW-FC82+_Y)E6(P(-$$QTYMdSxeT`13@BU_%78<< zqaCJM<+w_R&L>oyCGXyVJmPPAD`To`X89@z$9Wx)qW4hsj#v(9w)gEx4`W1XO{yy( zBNllJEI9ybM>1I|({|Ir9(ymLlDRZ6o6`kkv$^%w7gBFJ@@-_3z|$;{X(C+^bjChg zE}i=iQFQ;8LS|c$>vu_K2atm-rHLA{cZvMp2}s`&`G5xE(XSMoI=GsKpwhfAnU=FN zn8ndlt-f?aoxX%ao#`}78IMj{>dfsRZ@HPXRBjJ$6TnPb-U0Mf*%lIE%Z|vxayxo? zgO~Wa#CywiWmoy*v^RaqT&z}9pzp}Yz~th6k$Is6?j|2^`Dl^p#b?`2$cUK?SBXsb zDo;~>r~IwXTy}fgn`_LrojhkpWG*tj18kDW`pW0L&an4xsuIe*6Fxr__LDU?;vSQa zj);0W%I|QzFG4L@y+Zz0w_83sft+ja=xwhXq=w=dA#$Dmz3n|(rQr=Iri-khh*Yi@ ztKJdmepPp7-twzOrW2I6{7T3@j$2tp<3ynDj0`(%dvCdqboQ_Y~yUoNzP7I@#W4SkG`Ko9p6tP@2>*4`mnyY+WHW(LLp6qhCS) zXZoRA5aCezGqyC>E6twE$mR48(Qn5DPj>OQI#1U-CoiB%M|MSyFG5Bfhh(Gi0(2N~}qpd(z`Xr%nT7jlmynF=#8yv_)8h^b5HhK$Vt*53v5 zmYa!)Z~d@4rUpT1heO|8piW;Kq7HIt2xDNsDgYPS@p$=)Vq-`cCZ@HO^E(=3s zI$5eSv+F9#r$AhP2ToeSmV{IOeKY&6t;gZ5xK9*1qP*o#h+JFATQ0{g+c!PEq?Mw6( zIO;}qM{Pvf2IMPge|>j<>#7vFroMLv`l6(5J8v#vSMXlV^#vj7 z^o1d|D@6wR3Y~v#)b(W$>h#?_>cU{}ahxlFzC}WvzT8J$P$LQGTPD=$OMq;j_TGc@ z3dwITF+e}`$Pu5m`QJBEpJo;JrF@3?dKKv{PZXI(;w?fSww!EkK-tvz{7Tth6NaBfTK(4na8j?Stl~)gsrn z^iKHMbI9*GM?Bh;x}ETjr&8oyMD8i%_@6DHu4@lWFx`O;A2HNr<_PURqWt|YF>fT1 zU0;D`lC#NiOs(d`DaAO;)qaEgn%&D^xTSaI=ZNS1bJ**XSe}Lwkhi(n8G4&l-%m23PUk{(d^efhj>;Gj@?{K{6uv%4Rkn+# zZ|o9jC$AS8W~-Kci_WC8xw^;5(gkc+?8WPtF`tJbn|1KKL9MyLx`k}EkKXz!>b2LX zdy_rHEaCbnx(?|>w9|_(b*n3+Uc?zY7RT+-7eT4h7eT4xi=Z5Q@smSe2&GP62xa@N zo7R7onHAnNF z=tn*5I314r#n+zcEiV?Cjt_77b0X88-w*M4?3-1>4&4He`CCyh*A+(_p8@LSI!Y(V zr-B*O%YJp?&9Z$gIOZLb)A-bs@xNxWrXDV3z39G1 z-BnVdb|2o0`ZMx{wCf2oyJ*@zMU;nAUM;@Zc>bk0CW;H>lg@~>eCnPfV~Uc;Wf-B> zt2%vvL^Jd|BjFM9x4O&aqrJdeo^cNO zeInOp$=!wmjr3=}~6Z*x>U={fn`lsl-xEl(gUvUr#4&#Nxzc*W+t$m5q`v3W+(k0=-1H?*o|~L)9*`vuZIytP%xPO82TMpl~c)c z=wC&DG5!1KucZGP{deeZXNEr_e@@@?9sj7Ne~i8l$A1g@Rg9n;c_94+`bqR>($A)U zE&W^R-$nl+_%i+}sAB@-v`31Y#@;^#=y*tmi;i!(6<|yBX1}^@nTS;4EuSlL-Ak_W zx@}<|mHN*Y)c=!6bm#gg?^>nG-|ALLhIE*opxj(aJS;1>X4G45zT7-ZuH(;qQ*f3- z*!A~KygyyXMg1m5yuk?X|d zE!SU@>CERXe@x`sd?L4Qp6?uZ$>`l$PI(N-tIbP9rW)^?BLCq|ruCOZ++^DRzqfWx z?YG(4mu5}moq+b1uVReT>9gDVF~`}>PxD|u!{Fh2@ErQ4L3Mo7;J>nA?#*~-?-MDX zF6-UKP>Z)xCHxu zhhyyzU_bIj)SDgRwPYRf>bxUPkp#8xc+1}vxi(?F9OaiONG4L9hUyjax4NDp*F?SL zy+p1}ID{k_b(x&D1l4wk#YIjBihbhE!NwrlV{QAY)R zuS2-#_Yz`w{s!UF~x=RG4iggO@G-JLTGF>Z+wdbWhN#uRSq)?AB35 zC$6LtLY^Y zu}&e2DerEZV>;4J#gmllbfWGC`RF3$Ex+*`^1Oe_b)cDuZvLm@AM*F)?}ifoOXND; zcqi;D1!&WNe38h!Gind?n;KAv$l;QRyaT8_@Er0M=a4TDxo+RQGkT+sO!QiMZ^cpx z&`=4oMcz<}CyKmB1M##Hc|!$gN%<#z`B;S69^4|4w3E*#Y-1yTUSt}PxBP{3$X`5% z{AF*snP^|}RtT%pXTo%dc_*w@t$o5R6E{2iG}X87 z;!9nR{impc^m~2v?f)gu45~A$y0(8nuNA4z+dj-Id>1c!@9@&N>K+>2%;_8chqYy~ zvyVq#=&Vj(=&X+KVRj5>xy_6pBU$MtdT;qF0ccQfdAZ1SlD@hQWtgaui<`-KIbC`j zDYALc3ay}_nb~)ebp}yaL+%H3+{1`8Q|cB7`T(^1N^0`vpcDhCNRy=Gg{w8-CSaZEaC*?;w#ftw=h03J~?e9xIX8_%TsncKjXla)68xphTK0!{f ztsIW;$fgN@A@`s@@u%jvDPabHw?S)Gttm-gvJOmjzj44ErGNZ*^RicioEM#6RuSZU zrDR)SXH_Whk4Hw@(hs9Q zfPOsv(e$U#PobYfeDSP&qwkl1j0VvUr5{e; zO+S(TMEc3}GwJ85ubpc#1qJk1&@ZOHhJHEyO8VRB@1kE#|0sRO1;}V1{Sf-S=tqce zckUq+B+;KnKb8JG`g!!1(l4aHl70#Owe&0KZ=+vD{~-O^3wTfVBnAG1*$3!{(H}rR zp8jb1Q|PDA&!NANem?!>^o!`*Bg6jBl2I_Z$qKixC4=Hp`;Xnl&HGsq#mzf6Sv}_; zV%7VuaF;!{)Opol&-9V`&Y)>yrjE=H@XwV$^8G^O?#Z2S2W!9n!XLp}w zWh*P33w+9g-g7Q;`d0pCE#K;lj$IQ};)-QHRLTkewoN?Tjow>tZKRy5fVSkrW^Z>5j^tMJ+2yVR$+NrlfE-&)^N zzf!*qEtmVO_Fe9?#;2kQ{!J_LSzOw5Y18tiYnm4MWS01rH#_QA>3h_#t=|gYkclgN zf{J{L{EGZaCBC)3+nbd)S?jl{9f;mez@^j{v} z9~2Z)>Rari`Q0o5i+!q^1Qi7q`fm1JE@n%c*7)pdw%KQwe`(VVzU57JG%0Vgt@XCn zIr+X5Q&)&}aWl!ZueEcVGo{S^v2&H5|Fq0$+k95|BwF8n=Dg1C^iN$Z+asBx>$rxj zlOtc0m+F)*?xGdc+l!EF-DOo(eFbOMQ;~APEgaDb_PKKMh4Lm&uz3``jc zw#I=o$%BP8{=A`f`Q;YjeGs^ZA%KQfgU#e8&j;@%?<|3RrDQ~1UT5f!Cfev2yBr)e z0(|cb*yobx{03g?F$OshtRP=78N6*IB5*zio;V78SWeclOE3ZaS{~S(x-g(O*l!Z_ zPkxW^At~T~(o`DWV~%I|Kvq>1teypf_L7jz*MOTm1$N|uyNn0B$v<8J&btBnxw3`U z@aDJ&Q={et0oItu5vte5;?_&fG(bE#Z7H~jY^u;cHbCr66;8X!4(_;@HE50?Fg0k7 zCg}JM;tSPFZgFczXeX5R-*yWGt>v0aGfir%7e=M6+Wpj|l zRfXWf2cbX045b!>zaNVxDPIM4%8sg~M?c2YVD5?_bD-(2wMb>N>erTx{QN-t}~6_0^|-+FM1fk>cc z1NgMu1W@~>?}J}I1bg>Z@R7H`2R{dIkdyT^!%1I(b<}A1?PO_U`H74O991y5{Z=GU zLcXU1ICLlUqwYZjIlI6Y%ePY+;hNpx2jxcgKY8}eXY1epAM`h-}P<|(P*FNwp$*t;Z_JcoY0 zydM&{?~1eeLm94`fYA@`1orC>`yG>DFKnk@KbM=sB_cVjN*G{_OuZVR;iHvjbGF>{ zQ+>q%Bydw-=&J^S*Io;*jR5!E2QH4(`B&VhGUaLsGo!$(?uS89H2GO@bu9SOyOCgV zJouHV(C?7Gpzgp!;GkjPUwXlQGx=B6$X-t(3?5)7+9j)!x+^Y3fP5Lx>K008(-KyV z0^dI#>>dqHK8yrIWsy;L{2J)Z84Dw&U>e>&Q%Ce)%c7?2i5Q0fYZ<}HB=EgM5a6gJ zq;7z)){r^#V#U3PVBrMlZp#w>kmrfGgED7UBPCv+ zRr_DQY?sxo*aCwp8BXc~9!CaJBxC9>mA2LzNxB-GJq`A&bHNp|Dr$!2T?^J7kFtFx zhlC$~BREg?is}x?;Ir5NwKAU7{ZE!%JA#|Re#60uw}5}(Fs!>3{Ps7{S1to*^+ks5 zGn^zo(`0pp(Ca**1*m%f-1$41e^fB~K?ux5v6^fq3d7S+A;EZA_tpKyPFO|m{5FPh z-6POHK>MO1aFPq*s~!a(3Xm$$67QnmZn@%7-b;3p50X7ip|2)Scn2k}A^Ve$l3%`w z86xky037rfGH|o!G6*6lcwe?oS|fqd_Ub&}BEcl`>H=_qY^~I_ybzr81o+z!WGM4V zaE8n;TAo-+&Vegpi~Y}&5_fA<3Pp>Kl6 zw}Ia9n4#dJ4bZU=U5;;ddJZ<_wUm4q*E*5z#M} zWm6+8I)V&TJOTaMU%-3s0tyZgrEt;*TJAb zw#&+ye}Z!cLZ9#O)%-fPmq9*8*zfqq95@as}zI;#Adf)B_=tJ+sI z^+0fB0R%zKz+>5_=G=$%^O1nzTie0j@OW-846mAZwti;Iv$=FD*~5b;j=7M)04Flg zM;cZ{4c@HJrHI>|j|Am(W}B9D!>m&|faC)F70cvbq2`esv-o<&L;8O5? zOP~+C9K2&a;u}2!yxt-8uMxzjK+x|iWFT`k_;_CgNSy;-)C3VOBsaYZ`lVzuldd4= zUIKf$d2AQ(2p6jjf6agqvwC*=BAT5NW|Q9D(8_VX47eoI5C?}bM(oiXAoaL zk3u;uyKBwBt{lYwx@RQ}!mfm%PS$xf7;+VOXDB%3I`Eu_VLy*NaTN6Cm<+$^U~{~N z$)Gt-!(`ALv*CGEw#k}c%JoR#FMC@o7oRtP*L?|nIC(=P5=bP!KNR``@*>e|jh2&d zW{nQWLwrZFV4r-O%^t_sVTjOApBEDs%wbY_54hq%bjsv=!K3bleHHo5Kt^~U^u0TR z58e;HArhSWAo!9JaQ+Hq8UJOndDI&4djtko1b_=I@UwB?wvU6Y+Yv#~Q{d#Ow0{OX zW(@Q-&w&Td2d^vzUzY)1QzoqIZ@bqZs4j=Ws1L!RZ-FasMgoRkJPCcudgza`MoKq; zmnT4<`8N2}Z(#p-z{BKWAuVuxg|D5y<4qa&Dku_xx=SwyC%*^&a3eUR61?MSaMcIk zuZAGP+^yi7*d&>sfyZ9V8u}dEdMtRu7kV_QxWj)U!u%aDIPp7pz?a~mAApB^1^&7p zA_)8ztbIZ|-RRxm8<#>~Nj`c5!aEK?zf3lzYCq(l2Z9%5SgBygL2yJ5L@?zLc%mP8 z4f&OAh%o+p=!eS{kk;Vh!{8sdAK39Dc-G6X5BUlF68p?z4+THUrIALEPrhCb6}Q{y z2mtj@gyv+E13rkakotG-1DjJOS3R!rOaC*1MRHqRt9)BL zGPF@{G$>b*hmTcTR}Y4MQE!P)*Z=$>5Ip(> z63841K64W|X&5+Pj5R|m62V`wQ~8Yomrg(eQ$~YFvCpg=L;G70zL-4wEt!8b!n!0F zbU(-lCW0&P03VzL-p@8acoF#5#fUKFV(>z_&e!-Vr-J*lMo*H@FG76FFN6NE_FVt> zPKV&Uix9z(8Q{$2Xw$Z{z!Ntkg0|`4;$Gl+6Vh z#~X4W*f$UvXnQ5N<{9Y2^mljS7M#Zf7K0;h1&7`W{-!Iqa2fd1?&ze;mxFJoeQqK6 z7Y}bHFQy>A8!|BQAs7s~7JQQ2nG?@)3;Kg{H_NW_N5Rh}A_McD1&@pX?)5ZJ#2 zdQTy@ToDu$^TJ{!c>|};y5|vKZYr82mA{y8`z&}N`TiuZISuEj#bEOb`-@~-ufvu{ zm3SO++=AJ^#+NGoB>`1tPLA=B9gYT=rpKI!i*$oC$u(0Ep?v~?=ugSzx7ypsq6oL< zTyIVYxkL7Zs>cZ+(*EDjz??Z!D!p6{9Q=LuO|sl7o1;Zi?|`0XlQ_o7Em}K5+Na+K zHox!w?hAxBzYD)yt{c?e{t2k0@7O6*qYBI~YxA!|1m@?X>;1ug`ipdNTbKcJCd$P! z3^jZr_0C@4Qu2h!;3{(GVx+f0j+oK(9k-l@An0`@u>4o>Uh>f_L{PaF`mq)`^bK&q z1K?_M=Xiu4vJU#wGSzAZi^xl=;5#FKOPK$`E~u3D-q!a>c?IK zHfJ)8mgQ4R6uuD|x*-_);&`ngYSvL;u3KH{PF@U9=Qj>YovyB@hLq7URw#S{T@7>8=7g= z;2{q{U;YC)c!|`%W}xmz2u5-uN~{I{#Xb>#9DJ8-NYp<5FL1V2p|Zozu8|Jip$}~e zUe*%{rUZb$&juH^0sAiJma4cD1bfE8U`G$|6WkAk^#fm9gc@-~g2RS`tKz`=)r!_g zege2)KH{5q0XR5}JQ$qec@jC^#urfT9EK8&9tneO)1ei8I`rjPP<+-N-5$xhgT~G2hoZnt1G-xVoWQUB}}&>LPyd&8^tovrV@ z6})_gAJ+e=-65Db6A9kUi6t-voU#s`u3|QLZ5B8p9o%gQc=eUw>K1V6+b)#f$e z1#%Nhh!M$eE{w;8vG?_-|rzZ%D zGj~E4@~FhmXCgs!bmGSkg138UaNSpkV8=E@u#-7-e+oXcANrN#O|!vu+o8{wFQx1f zeF?6*9Qv?tz?Uxs57-4B+!gGp*$u(3lMzAq0q|+I>5A{cIe#EP$T9Fneqm8{9K3%t z`cT*(;JamurkymI94jSO4y%JcY=y0t@BjaV;G&%fP;df#V<-ZIp9KF92VQ;(Jmo6b z$DanD8OrdErgjs2D!11)LHjUDk=*_w^dY{`S6`xf>3?hdAb5EYN@&h8>N*8%&NH&Q zgUz`{$HQsQbB*G-e4F!)w#wq8O=8YJ+WaUoRICREi2H4T)VQoa4s(X#qB96!4nbTI z12$(CE;$4?XCd7sCDsJYnMiNRJso9pHqz~KwW}P_8VSC33-rltz?aGf#lHT}4~C#< z90IIt3+^kSwF-N+X8^7ZLpp*dq@YSuJAvO^1}^SG{gVjq=nj79LFhw!g3}ks{G&On z=*0k>O8xtQKkA7L<&h_F=G#WzB^wG2Z;slEkxr*9M{3zsJft(&oK>{wa%8A<0Q3$$ zSx*COpkRblk(Ri0APio420Zb6a3;4{8^{Y?(4UNeKA4;n3D(~=X?*j@L&%9y(4X)y zz;+7y$oj4UmPf;2vaEiZ!HF^8TP_6G#)8u?hW$bw8}+#pTtz;bf)bl!rF^dfo8zTC zAH9zN=KQI+ZeVkM)j>&JGhoiKI^7Ix&a*l)9ub;zufDX9!R0*fYV&gFrwm1g@3{dS zGR$U=qen6Xr6XX_{#|5X#YphfPDpUYDDVWii=`PV8Vi1NBoZ{o{+;(6I5`RW(fod4 z`FQXT?Vzu_P+8i4F*}htr77`87?>lO++wCpVqS1J<9Fz*E<%K{%s|_z;2i0+YM*im z_`HS4aQHOvAFUCeedL*>@2EWkK?Kh_dwvuWFlV5h`5A1^Lc6^SxQO;2-3?wtj%5kA zkzWr)hKiDrfq4^PUoNcaI|^@y!9g0lkq(2C(-FXjcSMfP0RI*W{g9d9r(Xl--3*>B zUp8wK`Rn5{;ymnxi}S(1a(NFeX=`=29rMnhpYpSl1DF8Kd%h@;QQc( zu?}2BE_)Tcx{NveYz+jZH2C>Ba5;JOGvHn1hn@rg#z>CRSw}6+E zhkgL|tfb(w3JBJazgZ8iBtKXN-bTKF8Qei0zzpssM?DYw8uHz%!FA-J#WqX(zlkc- z$7!^U1IZt}3l1TVV}^Q>eVCyL^24veK9T(ROW`G_EFJ-APM4BL2eVhBc2-rLZx&V+u=JK(KR(2w2--mTvm>H5Emg8j0^ z(upJaJs8}c1zzz!_=l;;K>i2dce+78U=w)L!$@E?c|kt)A42bH3Vkj4`+Z#hi#NmI z&v+Q*e*}Jb6(TVFPz>}{TcGz@1O3vi;9JjQ2DX78l})D>sQeRfXgKr}w}UUdMCKng z*zg$y+jzMg{snleY_nBgu><_+AVg40zGxuyVP8T&e+f8~JoqlymyjQoTQC}59XX^z z+Fu2=Um=1*+0!YPd=2(xlNjE61o}19=iCN9NPbyvz1s1SZyW&*`Ude0m77$mUqc?` zX#s<_-@>3oz5&rukU}oH69GbaRMV(m!RF|u-4`HyD)rs!pwA^w&p>>6QK2Hu@rmYiZz<0RzYP2v8Tx8X|l0!M%Qk{uNnHwZ<}!fe*wnf#cx6xLOvI zQx`)&?GM#U`*(f|f+2MX@T@&C$alfyzE#ji{0aShHqmBsIhW^?e?kAidf2C&1dpi( zC!PZT#?^AbX<9N#_6z&TC9X{}MC zAta7PDl z>kiO|cLqN#rPK`Mg@Sz;-{Kz4wEXfD@kbCrRZke)m4-GB>Si;v7DK0OsVI1Bbxo#2nMB z&>r)4V+sL(}+SiiJeLr)wkGU`CF=zbrvoD9`LSq;r@ca)ERFId-wpt@x zoe2G!dzs;h;9`Im#oy$bu(S>XHIp^3Mpf?w`y+j|@p=@5K*8>%oc6RaoMYJz^* z;2UHu&`uOW&fs;!${gs!?m&X(h>9+Q!RDxnBra~5^I(6++p3rT7jg{*sr-yjJ1{mDRZMHd7 z2mk5_r#M`9t7JcA|3f0GTH=`~W@fL!4_fc(lGwL|l_}#8>kaxJ3f= zdBxxo&r%q;pJ#x}!AD;J-^m11Ujo0u1lpE@C;f>CQ}jJ0;v#vAC8-R&vX%*wPcK6J zd1TN2YzXQocsc?B3~!HSfO14w#}eg{t7Wm#8mJ?GJ??C7%L3-TiSQ2Yipd_wLW?=1 zL3jryNN&xCO6th9A2EaE)7(}Y{e9e!7=EQQ<9~|@fl$$G9O zTJbhGmQ`r@@-XPPzXN^B-n03hHW+4YE11zhwg$$ zCcmE$U^6@22J#LjP*4N?LvjyDGgL<&$pmtKhQ4@gg}x%Bx!s4(EJr6x>Nl0cm?bxuj~i=c=F;t(2pjUb8$;0 zFPA=G-~TV6;5X?+TB6P5p@m?-LCC-r`@r$!YdEeKl3zX_`cm?zSAiYpBmAXF;1Kdt zw{ZQBpx|}8P2}5baG&0E#a;+#LH}^q;+sM!GVl^}h2~^9s>l*(&@~8@FVn5kM z^Yoof9=)q2f^rHxW#Db(zORG#k~_W(K1%NPJUDd-61;IWxPaWR7+gwjt#{cZy(+Tj z@k$7eQt;Zl;Gm(1(9H}EAV2yP^hxB0-vJkqpM4cvLVkA*xSSlNcTzP2V2|SnOK{K_ zJPU)oVaULrEI|ReoFynC_xk|$tB1qhRPkE!CKjNQY-%`kgxX8{n<^e)3*_hbtl}YL zQ^n`-ckzdt&!BWCna_>!G|B=Yxc^kns%96h0cD)%a0Z!83qH=KHC)RN<4Zj;xm0Fbu16PG703<;M?a=11rcT!3|{7rn|_dO>4=fNgd;mplQOkWYdJb z#(7{6`4JKvO@sXR!I@;E&m)@*uOyp3u$^p5e2{FK^eEXhX^1BY88B@+glw81m2679 zm~2X1L^dT}OEx9mPBsNNN;U=b_>DiiP1=$#eG4_viyX8L>?WIWK80**B$I5KFrRFi za0Qut#N#OSGT2NuRa#9pRqA&kGHgao7}@mdX=Kx>3&^Ghi^#};^#5`SOaj}{nLpH;zf^3G(UUGdCO+ViE<~wUeojF#N(a}fvJIMWYbG?$)=O$lg-4kl5Bc;rC0dGix9uDUrd%Jlkfi} z18XQSZMKVSMnT{dL|}UD5VEO}iDXkFnPijU#bnb*ipZlXJm}Ts6quQ-iflSf!Ntgc zX~SZ&8Fo9!CPPQbCPV&H5#BUu7`eBHi$gpGW-gydHgkCj+0@8FvRST|lT8y8lTC?B z$+0h?z(>iRi}hUS!j$Mw3m3QpqMmC1g`06=buTZYP@z?*)4trqi9I zff;sz(~u$4hM{DWfzf2ssdC7s309KLDA-Om!}zGpGX71QhFr=v=JJ_DHdQ!}Z2E}f zGT55}xXEVJnL zEo`svK)Ug7;_A_FEv;WN4Zn-V9{z|7?-_q>o; zOZMf&wVgbj3Dl5FxGndegAA_bw!0U(;7#qs(*GkU_~RAy>LKLTFM^ZF1OEqJNZzsv zTu9Dl0&B>}c%ib5{2s5gYRNP8N=n!NlN3a8>| zk35?-x|aMWYtWsB_zy^d?e#yEf>SRb!CdlGmMEY6A}>@{kn?zZ4sE677j zJjii51%V7uMgD|UT1`&oIIkn`*oN@_8OZRSk8flx2 z49#K_^dgU^{b=%W#-C!djQbqoSJL1uCRjlp&ni7g4rK<~<{-iD)DIvZXQxdfZ)X#vkPBG@ z1Fq!yzkqErS_JBTXOkq853rN%xC(l+x<$+bo5gDg*(|?FWV2Z1kj?%ecOKV&BPgbU zS$x)#&91hRY_{b)$YzsSO*WTiC&^}i5q>o?Y?k-u^a^=P3CbC#5uOR;=cgd9BB)|V2*fSyz5sqhsdv5~omAPF5I2M7gqrMf{BXhax zgUGMQu35Pod6rB(%KgYM$|z7COdcd_iLl3!O2J<;3e=#0eD7xP#G8?UcUU8t%0{z>vLGSMinCm)kuuDpjl zX*Jl7qsqYyhLaD=TA}vC$k$ft{eKapP%ulTUgi1Z0Lh{9Yvf89X3AU05ubot-i8vc zkzuL&h$Y~8pMnpQU*#xjy$t$a*Lq+ufC6_ZcrtmB%dwV5j?<9L-L5hqC=j{eNy^ECK^o$d|t2kdm4$y?d!4v~8@gTIl#Vjl>&4>fW>o1h)}3pT+xn`Qjp z_#$##@c;t2*atR~Kb5&(OEmpq=;t$mx#Z;^Ltjh|{Sf>NIf+y4bL7Ea$`?-(U#YUL z|I0!k$a@3{tXv1KdJ#N|GvCD(;2lpRfz*xQM`X{Z87v@AmU~LdPm$kcpLmWuo1@?b zVNKuRVw=5AgF~`m&|s#69!dGU>*5B9j6i?JplU0bXW?1OP;NxLO9U{{h!)Nh2JDw+6jeo z1EIfEd%bY`7K~44QejUa1t057CxZNzFvwsIb6SC0lRpRoFV^K(?4M{2?!+2s-v;~& z3-kmzLOZS4cL;|5HJwTI`IABlnro*JgGbxJV7X4E!sm4WPu5{7+%yDS!4fVdzrzf) z>^PMw-Xzlj|A zz4V~~*%2kmZ?MFTs|1ITGY3g06nz-^m+M6D5kWWwZFC+Gjv(KV2aYG-mV^ir$?e*K zlgP!ocF0o^B_oi5GrBeiZzdOO4GKHPK;K-N#G`@`3XW)rgd@mpbPFb&L>{R%B3w)! zqfH=OPTryukMMSKH=QShtI30Po)C77MFyI@rR%>4LMZr+Im{z(&|xI{Lh^L&M8YNH z!LNXm#v#IqtbrWzbGllJeE~UN7ds74-o4rbK?MbSn8PaaXzfH2AS4M1+|CTdlQVTO z5`8lH1)Vp9bII4T213Rod?w?MAP@GiinmkHPJ5+9u$Mef=YHX!3lV{j4m;rpa%X06 z3b~~YE6o7;4&7e}`%gglWL;f_!^oZ=ba4ZJPUS)U^?2qfbA>pgZ zZCJvf$}z$0j%bSZeZ z8HVI_Y~osSDw`BJlG|y9TggmF9xspNv<#9?`-ulR%2ERn)Y72N7hFfy1J6|N_!RbY zsrM%zW`rSRJ?=~G!^zWSace0*R7oVSC6Dk>aCEN(5QCBANsl8y64`GEIGMb^EjX1t zOSaV-K9{^z){?Gmq{QUZt>EqC=-tE*y&#R|F3kz9M&a?>)dN}HQC=enG<1zFe4$;yn1 ziHS^zjLXSNPso-eVl$$mGZQi*vdcE!9^mIwb}A=ebnCL+ivk{KY4!OsprsX26wthT zOr#zCxg)lw6a{o>nI0dP5tEr78{>}4$c`(Udsjfmz_|F_`PVJXNL!E@eO=aqs7U$m zinMuGEXta5;}r{Y=48)HyJ7wU$xmcNT10GmR!mxqJ1QeCHq(my#MQR!zJ~+e>S`UH z70{x)dqLVYne(rnbItr~7G*7%FF~T*8SXT9W_qMMD<(QUrfkI8fEK=*>tL%i-xY58 z6u3IH%#KcvkI#sTh>ev}MwX3T7w|wk>%&}EU+d0su8B>qkBqgte;g3f(j60-o}Dgs z8ELWc?y^s}1}tr6xh+?lve!NjSmicCt zoBEQqwQ5WmTO=gJ#%5)vyQ4ERGu&mJPXrYDS|LXR29%9D6|kvEeLMPhiMN|^K~~26 zYpz?k;QF)s2-+|{B5pl zn%C!A>Mzc&zh37a#`RSggDT9($V!h%b0@^P-I+1*R;#;QkLq9ywayEdwk}F@1+|Pz zPl(Noh>MEJjEIVhDJ#CqRoUgAY5rf@EcpM}#6f8ZZg+HcR76@rLR>^fOq3;)SRbo& zUBDOCQxjb6%I1~0Mm4jZi*sF8_UbFHXY7uQDeeDU8IrgEbM+-;#Je*ivtlEn)3T!@ z%O`1#4iCMR_K|47G=+txvuYR zHT}*NWKH|d^?=oCx2t3KgtVCGwCJc4U6pyIs*e zGBXllGBRT0BC}-njETuej}SjAJuNFeB05UybWpVQz;~`->($+^+_1)str2@%%Pvey zi;K*R$&Qp}NY9E-kBf+kiil2+$c{*ekeo-y42n!}%t@2Edr+hCy|c%aWSzg)b@POb z?DUAZ>_{1cQ86+X#<`=TBO+sCGGk(5WyXt-9rR!09F$;r4#|qpWuNOM>*zjLe$U2o zF~}Wnb>Hne&#Kt(@^8Ejs`tCDZM+Vm;{R(M+;qSdZH4c4b@xP?Fj;PQY<6}+T3no4 z8ZIL(KEWLmmmV3FohCwAa|hL1Hr^H{&PHn?(kI^9xJRm?$3fQ^tMH&}s;ALLF_C9P z$HyncMMq{Pq{m0bM#X2wXGEsOMQ7>U?@mjI8DtC_EtxUY>~{TscHDTYWsAUY$#kn9 zrMYiC&Hmmsu<=%W@q5>`jav;l?7HJWv~}EnZR>r9UE|o+CQPF>5@{?O zZ);=uAKE$&qvVNd*Ai>|53ZXVZ)+2IqZu}ajpo7_Mny%YSshyhcClLiD6N?OqwCqm zo2Ktiu4}tDnuK-nPcpe}`^h!yKQv?Pe{II`HPVc4)wudkY;-F8uW=5N&8asQxItMhNJ^SU=S ziN~Np{&Pw(R(`X!eD0 z?~|@{-=D6T;~Oof$wFfrLd$u=6=mf#4eZ{}1ZgZUvN^nMQb3ooZ6{pAeHyQq{wG~4 z8@D=qQfhDdDObNqjaORKf9=Fkay_s|wgI1ix;1v)59(cdC#wV~-;}!9}PvHE3Zk=g0dv9YmoTOcznHcR%Z?#OiA z^ra`HWeke6@?Emrn9MX*(PAIIR~oQo)4<5_jczARtc^8{HK%D{RO59VX>TR1*CcIg zS+l^W8*jVu%>%nMZgpq#z*&u7endxLr5)rSIKz6)KXBTAm|!FRV;ft2oPm$`Y`i`r ztXaog=lMifUH3^Nqy_{oX?%i>u&(lx33i|>FtYLP5Mgcg6=RPWH$LdLy8?fo&}gPj z9W>Sn21Q^cXwf2YTDX04SpGY)JFr52@;OERl$+MJlRM|OTyF7qjDMtMU`i$7`S8zk;`PSg^7k{ui@VCCp_qX5Dd~{*|tOZZp z^iBR1aqW-Q`MjEO_qZ+1zwG|MDUa?R_|RS7{(k`h82;z*+*lUOQ#mmE;LogY)i7`$!bsi!yPX3-5xTi^Km9IS2>471!cVc;sh*0TQ|9UXPU1mBmCi(izH z{s}pR=K3Ct@{jGU=%&IT^%{-;5F(rx*^e{owsStR4z@=VrbezX+PnYnWKw!v6IUo& zFl8ds)-lFGDo`t@O>(@Qb&A=LwKSBnUqlS0ac1^cE3Aw(u(# z1WNp?uEsEk^aW&IBM9HX!xw)g0-3MUJA3kYbmLNyVss$_34kuzS}51=T7$htXUxKb z2e`;qAV&yy=K7x$vJ$c3v0m4(e=&CS_*wr6??S>fkRb^Dlf`a0J8@Byy^Lu!2S0;E zkRV>4!1cJl5E7Xs7`G5OpWZJYuQk^U-nlQe68=Od@R>E~_*-qj`3R`FpsFx39=V?O zZvC3At5AU5l~u3`#>!7%a7f6_(d=JUF5Yg$S(tHBD6Cc!vpq-FhzXN*f7G%%mLgKZ zt{uQ&z&zc3RNY7^BiwUgiC;h%9}Wm7fofZ}BL=1&Tu_dx$ny@5_}^V^xqV<2(uO{~ z>CW6L0^rb^e{BCeTY}d+n;~&JJVd8pv!fQwwc38rkpTM;oJwZ82Pl*7yA%lbd1^l} zxz1%-!G38NL>lEV@>qrRe=+5=5M^Lv3La@TP!0lC; zpe89881_3osd{Za)f)}(KyEYbr#k5Hnjh4&vJqGh230Y~a3B2o2 zwqNM8dM1Q`zZ$$CFRJ!L0SEIwsPj*h{LQ{|46!Yl8px`N;J&?(fB$rSrJvSGB@qHi z*t6nsr+DNiS~M9#bY`lemM4aglA%E)czvGeyjLL$6)3NG?MtD~n*9?_+$ioiU?`6> z89rIZK9Ug9JUk~*Yaj?gm$h*r(RAGeTk-c?zOM=mlCD**VJ)z$RIe~S0MJfno^{V4 z)#SW^HA_lcaHH=ifB4K+2)A|L=0*#VdUD@R1RkTO#cBst#sSbk{L84?kwg2kux6(a z7y8Lv50(zG@sl#X8tc)@7~(CJ`uwE=6zrYwuric`*sL40`+Gw~iR5EOF~{PD1Jzz~ z{82RPvP?zT@{Ju-GHk1dxHGNDFl2HrWQART>J;vp^H4wBl4 zIP5+j{q-b|yGKkP$2zk;h>I~)i0o1=JjbjB=YXDm z`QLptl5WcYe_Sn4&9C*~_YVqT=Y|H)Mw<_Wk3PB$X4PT*#7${_FMpNo1gO3uzw)}) zGo}dC>;Sb)ls+V|{^%QuZhjDR3oLvA5b*D`WKLHsUu~fkNqjVz#=k|>bSO=}oz5re zV?pb{L+`>SMe3MP*jh8OnJKk-m0)R{~8pe zQ|VQjA+Tgoj3_YooJxFB5&9u6qt1tkznIH8UL3V6&?J21Xo47VQUt-*6kmDgkGqrm zV@cgasGoVR4Ju-q{5&gK!NZqYpgb8R*HjD?f5)Ry@`xw|-YlZj#C2LVODX3`dx5WH zw>k*Qrq%@r@L+*P4}j^sJJB3DPk=C6Caj${VIOJK*S6kKP+fvLo+-)+*a%M%abhw8 znV>%N#6hAr4^c=o94RKVwbHy~+2A+NXHDk;+YqU`s(hQ7gw2$L-e+IsX>l#fBooK~ ze=abMQ4icz1qID+XdSF@O)BF_g7^NtS$dVY2*Oc?xnh~` z7I@ABpfw@Wpfzc3-rT=%{IR2Cyu@f~mJ>VB9#F~-CZq8*W^Du)9L?WI2Y6NG^O4`C zrvi6EOj^pQQi0_>aI{3k4`Np@oxEf{exLB$y-<+&1 zDqDH8!3AFVJE~`)#gWUHiOX-~*$Gfomx#+4GBn7c?+V{kkiXK7V`w}UN!BxdLu}N5 z-#)p}4Rlmf&KC1@omu2I`b-fdpj-`Mof)vcZ*>@nQH2=|{)ze(lqcYarY_?szL}u? zZZp-r)mL-_yiXBhE9cs%4^{>|u+D=4Ud9+rhE9Ps?^X_YXHwrlC5{egP zpQx=NIElN^1a;X@V~ObJo4Z4F4^*|%!l+`#!36hC@g0lD-8$jbT!Nc>f0FsGi6<{? z&is?f@q&8U)PDOR=Ab99QqRT}V9aQ3`Vj}X>7*@SklFBL1OHblMv6Kror)R zNJU*ncFn2FHZ8vWEd<4pe+ke4maC??lMo9J3TxPegE<~BUX(jp!jR*kN8^aMp$UVJ zFiBJ8@i4+kg5PIoSYonW|3Crk!H=i&B(_5+E(l~#m-X6c6%zdlIC&)s`-31>;xiN< z>of86I-kr_FOI&eRC>#rI_hR`ksYvZ__CXJ--$2Ok{YvC$9t})f1BE$-k%tR^!*AV|FH)# z!L#&>NVCsyp}924rLCq(>L2pU>WxsD8i2&f)`2SVLq37xu$gMQYk#@@*k%>$rLIWhbCMJBnmF8mfcK{h0-*U_p9k1pnqRx)S5#32~EDm zU1Jf*SC#TCH-zI34Z~WuBIDH=4<>{fKwZ*wt`lq@!v3fjf6?|^i(@VHIfN*V=KJi+ z61aX{E7@(dEobd_677juXiX?1jI@|7pl)=e_lKGjd#7amYLKU*GY+)1ESx#fP(zS- zI^OQTsKr~+V&O1a7EnH^{LkRbc7_=D1(H6$uo5%NB_Pf}N3lI5u%bmY=^fDL1ywt* zO4>CVPc9SKe=F$MlhpnRydPYV3#%?5+8j|R7>1`$e~*unBHF+Q0D--%M!s)PH+eX( z(h3q4#%ALuW3=w$e=U3(^B9lh!IBo#>zbK%rWVmiOlc8W#g%$C|KpJ)6`e#x2-_Te zZ=AxGnmAL*AB%UWoUDpHJgzG?sah)@mp4J_G%jEWfAf6YDEfj8Eo<^|2S{@9(z?`2 z@!!5%sBQ_nBD%`ZwqtBCN^bdQd^kg`J59pZG9Ua0tpOsec8%-?lw~9wx;Y*yrImn7 z$Y1H`=fw7>7I8FQ{Nloc^wI+3A84~AhNexXL`#aIo71h)zp|d$@GM7Hc1#UVfEMwH zZf5g6e;^;Oe?j3f>i=#%rq>tUX66TQTOu;im?3tiH9O8dV7sb#7Yt31V8=R2qZeX? z&m^KcDHA&4_CR}smN?+BLPeY+2+X*LUqO;RYF955FM(h#5aP)$xJHPqiAD1&FYHsy z#A=%}O4ra-vZI%%7rbvaxD@uR#*-8w?EbEpt#jzTv zqt$Lb3Yxe{kiJ(p|5|=*b#W_q%+KGi6ZMz-(C9u$PRdqNwWne0hwF=kxESXL<@X(A z3@hdh_h1cb<@3rXhY(4Bn{$g`_q6LQ8a-&bAlSA_d}13t75;IK#L+?6tepF$APTEUrEH;A#Q)#=$X+*5#9N z4_@bPyxwLkPRP_ijF1EA#n}I_0o6H}f4gZv1+_y*^1^&tS#LU%8@+;^Z~`QUHl^D2 zTCAv)tbB{BV75BJ*{rSoi{N{On@teCs{Z2MkY16ja-oTt!nlK9%=uYacBPP0JotSx z>E;;iCy#-ZjYi{GcFwuX&vsCuI1zd4Gv#2<^uuMV`M%|_nlyL88NA0I#*-mCe>tm2 zC~g=gWy3HtZQtp+HMY<>Pkle;{nW=q(yHIv?wO)#IH@OnT&h8LK`z;c~}`A53hOaE8Uxuf5Kf7)}vhu zYS$*bKhMoneD%6|p&e!{G&L&+zk+RTt9lmMEXY1LW@l?Ivc^ormEf+5z3cBCG5+Y} z^k=$lp6_XEvOBFP?RJ-UZ6MwGviQTUHE2#4ERGwjlg%G z5>%|lMH4bzP__U*HTV_nQ-v8W^nF5LHJ{jQQlh2POWgaX?v;yqC#c4sa%F`wJIPX) zwl#8RRtr*cL15f3>$`gB2PUAdCv%068QQ#PQQCk}L-Qk*0jXDwHLMH}5?ZaI&nilJ^C%mofvH||Y-kg`93+z_T8h~>U zDy%&o`kN{{Ik+k%WSg8+HqXWl{?@(st@IVi5nbU>RJQ!{dFV#nc~3inrhU)}f4;b{ z-^gkw6^$VW!ujjof6$@k*F(&0%fgs~SASLRdh60ie-KcmWvj=Z`lA&bXk#sW zD1fHQt9Kbshbttv_!e*7@_>OuDD>q8{Lu(`n-%{R%_DWmqu%gS&gS;Ls}1wM`8H^N zVh!c|_K!^hit_7VV;+%>q}xPr%~aJNAKQ~PZ1{g9yt-UcGtGNJpG;DS%7xw=L;pt? zw-~nTv+|MLe+0EHJ!UW3wPcJb!n4pDP}?MT)glR%-E+yp^!eTHEN%~!8ZcSMP(@j< z?x`E<;X-O@q~pb!113DNe5Q8ZKtHz*=VK?rNT=GaOK}KCTM|163dSW81*0BCvk<23 zCqxvC1qa!Z*&v=#8_27B2^U*9;B?1uNi=3;}hl=8RAT5i6V9*+o6C zOb#G~Mj3w6=7Vi>9C{?S7{Q7M$jhJ9Nod)Vap+5bh03ncntk@T?v29*)I#=O>-~;? z9pS27lo`WSPa$eN)=z5XXSEESjnPZ=W4AB~2H>s(XX)OoL(a^o<^|Y@zYAHk&jAlUiQ#7K8hY?o2?=fup`br0tm{Ss#ap)xRIT>%q#IX86LLkt2V-Ng`jid0`<$RRV-G_hut< zmS>RB^YJ;<{vjE)9BmSe^bugP(9F{lLwiuM+{?S;MXkQ`jh<2J##u6R%vEQHW0 z7|s%<mHBpG*j3BhOXgo{7s1nn#BO?ixLgx7TA zKe6<7be(^TOt(4}T8oWmT&vhXLK(A~$3;{ZRn-PmxvGGHK{l096ICsdVWjoHE~woW z6)BPdDP}_>WSk~AyDUxpIUBx@ynUJHzHIorWG?PmX%~HOXsfW(@f&zVu=_o58v>fY z`&y+l^1v|lzXxR`Fxu@Y^Gr^qI9Ab>Gxdt7C=-8Z_cK<})**}4SH%KO1#WVbspX07 zxaC`cOzMqzSb#mC+HW&NS^v;!(@4pOx9E=3bZX6mB&`3QxA*cvY3ThYFaY_1w!%~B zlQLs`z54$IZ3RFWh?L1Wm+ABlKU;<5J5`uJvND)kNM^X}Cy1zuM_sr}$gRs~BoU8v+v?BzJy)z>7p{;4JM? zKr|f16W(WCJtXK~efJaC9RjT9hS)@rrtxXyf(z*x7=$+~jJfZE*=HTkecgaQ7*)i! z9DIpG{$V*m>EYI-(cTPzH_CD@r>xW;%0xj z)kN;F2a)yb>zoEreq(iMY`BQCwDq^qCwiGdV)!l8m!$+yH+X>-xSE(Tvzo;inRGC$ zxZiY%xldp|vKEGUpp;P_-O65Z7q%k>7MC@noL@OBvcA04u7E*o0QIG77rf;VO_jM2 zDR9X_;G)B1WvSz%qqh^;4KO=AlB7v|BuT*rrJp6F0hhn4|ITwP8Os)pS09DZZwWUa vQWn3tUk>sE+ zBh}*C&ML5Yr|hgDj8*FV%nRKg3XI7@`-y%gT%h9qYb4S^?d>stFR%>)Y5Bs=YO2_FtQTj&J1qm7OPc&3ayo4 zHA`~q<1CHRN>8n3E8O~!)$Fv}P_l-Z+{OQM-TQ}DXsqOGRJHe_N$j-yvT=CxLxtZ7 zPf1g>f-eQ{(P%j36a1n?v<<=Eu+KfEZ`>uR*5)PEoF0&R~{>jwGzJK|jtkz?PwFopS0N)Pn{O~7ei2qvR zPrN&tdrRdZytK|Ej@25XeU3dP6-#^aGYHAg*#8uZ^~^OLJxPiU-uW4&a}00PxCgJK zR~CMewb)HQbdv4y%t<_RoD^@-OGP#Zl^wcZdp24gKS7FNB7r43sa*O&FDv!=R3>iu z8TSAmB}ILCgOw(PnI?mtLlMm!o7 z9-sOzJZ^CEsFUmpcOWmgbJw`LaDw@Cj`67<2hO}y&TfulvED0M-U3!bV17m_SUTlp zY*5xUl-II9I(K6F=2PNoD_nJ^^7Auj{+-UO$JwUlMz3PfbLax?lTWat&0~CC6Xc&% z`>JppyVZP#aV5x1(V13e?QxR{30irH8doko!4~-B#J%|lnrr?G&C?ak$JgkUpwVo0 zg2npoqMc8$i@r(Je1e($4%0u6vvYn)wEFm7{}#D~E!oY95}jP?o}cm2QBv#+(}G94CS?)12=5puffBlh0O4Z1YicZ#TISepU2qgkQwyCF_sh>;eQ4|Ig1Xw;W*(XSHTWHJH~QD zhtLDZ*x^tUeeW1M7iy(%A7l4Jjdb%dW;Dh6Gc<7&N^(^zcbRs~&scMeWtvvg8OPXV zQ$*|})YhPu6i66XL3Rp5A1}%*$uemkwle3>m%lJH4_qmwO7fG(SX`KmrXOST!XjdA zk7${MvgM6h1}iOl9AhWKEVMmnhOMV=$JnCq9Qw;qb}2m0=fr6A(O;^09~#XpEr-xk zN7F&8}Tfh102Ugz4saFu8RSg)uo1a^z~-?I=4F8Asb5Wi)C9 z)gNW6qhe^?hkFl4?IQHG4_U6oLYI8VR$F4}iyyM1mcw-5hipMBEA1l+gW3D70%*4n z*_l=!`&`O|@RL;oJ)g<8wBAV1A7RODtn|zgHmOYvJ$Zz!ZF4v$Uk5u>ZM4#9qc;yL z(p3ukJb`CLI^f!mXCa-^MzzgKn`WCes1wqaw9=j3jb|ZU2T0lW1GdY$hYmf$a@wZT zUPsujwp(bx5tb31PNgGzH$~5&^yv?nPkSpJ`vHq@pG?y~VDsABXyOO#FbX?~!icpU zqG;p?do3Nd5TErUA(>I_)>R|f=N-4vR}ZrVu~wRQm~DworZW$-OR=XPDcL^`J&-IH z&x&Ng^%S1}PO>7@DgCz9Qyzn7A=#Jjlj46LLchiN+#d0OonJ?=A)S|+en+ivqS@0L zJJBoev)?*TqW^xMWp-Je_w_+i49`%m1|HRkeg^yj!aL}sN)dRJdM)r6Q0I+0r7T4! z7l=TGGT|*A1%D6tg-i&!fj69i0J4feFm;6F0YL)oz24X2l)q1w5JVd;nIo7z&PJz# z;W%sP1R)QGZvo_S#;LI=t7ECn0zK0(`cawjK1=T!M<08iE$W&?!D0pC={KL16=1qa!XZYHmvGSt9w_>c%J?9FZlpNlAR+W(gsY)`jb<99%`To=|T zxST)4;<{(hlZV*S?hEq1IPh?nd<>TUu1m-x*gcH0zw45l!2eK}U|@+Z$;r^Vr28R$ z-%2cON4%fU7$JogW`<_4kK=PqqalSzXUK@g=}g8UmfmA5?Rki8>#;O%KqE=itfnV8 z3;G*lsnw;_J&!icn;4iV@AzLNn&KkSO&D2?M@ro(Nn-CLv@m@>T+59hfRONv@*ZR_ zJ;>87)WT{LUZNQlY+j;;4y<4s6El5Q0zwK^omRncc0bV?zep4{SBvK2Ip1H}R|i6o zl2jM@ku)Dk<=L-^v`^GIo8}H@W0N-0zQftAq&f8QgDkhFm8KkIYkS5S;~`A6Z`evw zN)VO;?UxXmVh^&fd#=b!+E0qjPW@njDFaO+vRRj(F&%Y^vj8id@f_@gdrO0hLUyP} z{)al`rRsnj?XKa_%T=fwhq^}%)Jzq3`wRlnL-8U^1Zi#{<{RqB&68wNUehe4&I@I0 z_A{T}CcQ6;m?J4Le)lld{Fk6J@=)l|5qkkVh4v*p2>&!O-%VbE-z8CQ@|OP6*(zir zrTdvza)j3l3gG~I`T=(TD-#=>9Bq6WMaLIUsI9tRzpsL()LEqbj0wZoisTqNau_?1 zY|#%ICI#}6UhYQrXY%;ijvDU-JP9Ldr=b+7ws`+*p{?x3(A2V9qfYLy3}cJ>m^y?t zX%gI|Nr3Whv|kqbsXRAWf7>V(v#778&`U$vq7}V1m zeQK!CW03s~G+e)r6jw;nz8b}I5_=UiBV;)?6x^q*C4np|RUcvPC>3Wz%Hx2{a#yAO zYhfxlKCxr>P-aWDbl#yL4YV(O&@tuaN)LGpkPTZw0xzMn3`?G2=cPrRt=CC)!mrn)Nivo4Ki31{q6n$@ zF08~LUHd#wXZShWO&VDhoKjbFGC;BR`N61PXsf%PXREteXsf%o%=Q3QFOA$m!&lyH zM(S#O@h94(8RY8bQgO}65s8s*(rj4O$Qtxi9x4-~L9qS{0DeX4>c1g%2H3bkIx?pw z0A+&b==6Wq3|OeO7Oe6s6Ju8*u2t?85a3>)Zl> zu==boQlQQ%5G;UQIzUL&y@9$@=)0Pe?6K1;e$k4)FzJgA;qILLkbgm)WLv9DmHPGP|p~IEXCB(0RF0U-ZGxRTT zk9(dJ7XaRzWmWqK<#{9Lk>Xom@gCT#gC44yrK;@urYh`C1-n&gDQa1Nb!a_}G80Ta z7#)!S=df3ZhXGrKluU>?4)xAX$|mR|Fm?}&)q$ZqV5m00?ftvKZtsJsJh=+qKRR71 zE`zRaf1@j_(V6UbbVmEVpY&z7Fc@n(Np-a|z1!7ROLD+TNfzdP1>vw}yL(wpAE|C% zp|Mt2TnQ{?>g2y4S7uLXu%vKwZ92L@jQE2}f11#r!AgH#d0Z-fUnw)9EL17`0c8#l z6DHpU?SvC>tb|I@z9x*ob{;nUuh2#{ebs9n+ZxYq_ccCh49tN=)W8Z#JRgjM7k;XT znHd_`a_I7VA63|>=-sWpKKMFJ_GUn8-M!${y4tW*j7XI|VUqg*R|Q9>jKr^0(|!+S zcVU{XuEREO!Zz;-+r;2eJS5CAZy*LD?7TiLisdzHnb%ZCthfaVqJoes;oX86j3=jS z7dmyI3|U9H7S4;ba9*T@b2v&7&bRL&#jSwzZ{YIeEgIlI02uoBfDLeB{Hz764`6FC zt`>_0whF5p1&xS~+rL{)k{jwI_lCM%sEa}d^uVv>csW4g1jdemB!MJc`**cWNm5Jn04Dc$ru8F|&2PD3Rzu)m!3g26R z_9ePewZeWP(cW+n39bW1$$AY6H8(LPe*id<4Fa+YyV>}X2v#w}Eq#`^jCG=-iJhCv zKem$OEl35CBz&H-mlTV{!JwChM~;zZZ$aRffTaSKU~-lTmz~s|y)p

    z6=mlKiT)LFEJX2fv4h#IAu+VoU}hO=rGNBi=|hvL=U}#CsD(;{*{-4SG1*u@G-oxF zYbNRuEJ9>+KQKHrqpT)OsuLV2WH9pfL^7XYJw={hGZAUnWTasle~SjN@x$UGu0lf& zda_pvoZ5}8TH`+85k?;o$#xCv*#eDswC#cnHAF6j+@l7tJHz7W$=xh=cqZMsn=Kt4 zPoL_?jt*Z+4To93j9k<0#~vg<*+C*_1V5Lru?LZbg;u0O*p81blOmBv> z^&{iy+Y#){NE6L0VOK|X9V8h3URQUeT2}{Kl&h*EIn0LQP ztCO-N**zL=R+m`R(IpNt?uq^IP!@t^6N`qIKoou#FXkMM3<_r zT4tpSS6IFz%HX0D)?lGRjPFo(NU(}%?6l1D1KE(#G4$=n*aH0gn!~n@?wwX-E=RBz zT@3Y9Z`H|{K;_SNQt@r{h%+A}m^vUaC^C!0K!X)YK{Yt|sU5S9iKXiYvdl4Y^woiE z#h8|P|FvJ<+(n98qi_FL|E&d_>Hh(4IpD;+y;PS`n*$rLNuAv>uEOl^?j*%x&i%g# zy|{~Ij*aX0N?kn<0IvOt-b5x7r06#dx-7ujh=^S;0mch3qJIV$q=)(^VIVs*Hp1(t z+Irp%lL^D5C&JOP*4pn4A_Y%htVlL2*VRS7=&^$YBO2(lfkCu z;tfVL-zq8VJYNIb7x?>pCtLfZ#q<6EQLUGkvk#vPGj;*FW2kfpR{&!X=&lW5zddR6 zzbXJl4DOLq*9u^}cZ!J9^0-J#PkGDL_4U^#&g$MMk>SxS)cbjE>wtoI91p`f6|n2Ih9lthdvn5o2=Z7w9<6nrAasQsxX7y?)I zyAQ{hwE`9~<{9*hON=SEft(U!K+YLs95Winm?2P8qZo7IDI>K8v#+0urT^#0yvE1U z;}clY_;|W^0-J-MQa@%NAK#-oK`Opi=q1;Uz)WzII=vLLLo;&x+S^E_CFz=oHCML! z;?Gnz1$JpD^=7AGxo%UK3=zO*K>zXC*QcuHcc?n z`~BI02@&*68ap?^M)&k!rYw^Y*ejc0uQZrhdX_bG|BS}S7i!4!*{fNR1NZnz#TQ_F z(H^0yTY)JExAFm8YAsZFKru`a%#4cZ??<_C0zx!0R2u0h)XO)9_AlGa{>bXqT!gS{ zH`xJMK2K$F*{wQ?609kUl8;kW4PBWyx~%5kW6EmU(y|&ztj5YPyLT8{oUI185twq0 zLI#c6szQI++?RcxeU3i8li739sjrRQ%2`B@>}T^PPNMIovWpXq)czQ|HE|Ao?J<`7 z^ew7y%W|GsN=ri6)o0@AFcY&(il^VTVPhvH(_^V@X(+t_}*(T!Cwa>X^l(1kAAQr*S98gd-^lJge@oiZ8w0K&b!WK_U&bt5!9Z*rP zoAul&={~3`i%#Ao*fqhhOEJUxU!B^_E|#05!2bnD02lE9E>9#TkF=88Wu!Rp0pQ=l z{R%h{zy25DYQTwEm#_g$%QYLoWaopv?8LLSJbPcMcr@@NqOR%4--@~ss2heqN1>ZM z6u*P;SEcJ;cK${^p9I{Z|BoZsIne($0f*Qsl8Q>yk4L?5UIXwfrnXt)y_K8XTfm{* zcB8&47dzf#Q6Z+EU130C_9rp`N1;xB4h=>86FzSio)hsrw2U2?9&eci-h{0W);jV% zREr%Z!Q0z-?pnrtW*7(N2rz8$oiRVK=rHuNScdNas%`Ms8h=7PiWzG|WTa>Zlf8Hy z9v8OyEt@_gI3gXT&q-3eaCJREL=Y>$uP-nJmWgPYjA&V8j%u#PuxmY(Xt`LMpgj*G zaGju?zyz&3Q08kBwDx`3{TW7&DX?Gz#!A>si|gF%-ZXV?R-nzz{Q9zs<64FlNuZ`g z&TBmzsFs4_cezUBq%H(%)8H)B$XRaFW@iFjpB)b(rxX2efEAJRIAn81&Mn}~268_j z6<7jtB64m8sb0B_Bc~nsw8+W$+F+J3%b!*Tut~F$Xe)2FWmXIg@n&c6)7+cgnH5L3 z>sajU9%4RH(>4h65l^fq!#||3d9%kRyZ}a;4*5AK%feb|)-sQsH6LKft*e;-pc!IQ zS|61ep7N4g6pNlyLjRM*PS5F)4)j-oN!?W}CP{F%Ra*^mC15N3rS5f@-QU5?{$4<8 zok+y2z%OAmk*^KAflTxtu{o~*)bpsQl3aPxr%+}A1h&c*q zHOUmoxte6YkFus3*k@xG=bGr&EOuvZzr5#?rQ*)2yQ=7o^wnrUf}FZs5~d8uG>{rFrSX6~0DSc)>DhZT-B|y<-F*~OP4QQjqpK&g6?;vQ z>AlcIY>cE}W5iz?X~fum!3zswFoFG-yxGaUy~F-FnH2v4GZSm|8?Yf$hhtpM`mlYE z`@e(wUr}FkOp@~{k^PI=f_-rwPLRF(68%>I6b*g3Zgx~o!vQLqV{BFJcxrl@3G8-@pM%(TYWH& zF73lk92`$)^x11Ubd@xcvd<)DI&3m+OL`!s*hDK>tggwo^JYU18!2DQCLK=lmZEV*EM%p`!ef+@;IyITaABmt7BUt8B;DsZI2;F-ZwNAysePF3LmM5_hb{duw{M?3UE2Nsznk>ODJ@z;K3k`lbww_M`J|7FxPWbznHwd`1TiKlxu{1fH z#hi>t`Vg&_dj%?1;?#0AAkSl)p1>ZQ8or3KarZrX2n^+D^UfCKe9)GYi#(=6wsxrz ztnEiF1HyJl#mkei4elnLRb+*!jQS|M0p{38K>@e7KY)1=<`go~i~aP`>vU{yw)mfM z^zq*8z&}rWDH_XfA+OlZR(x!uFScZ7KHf!#__9U+veDBMe03noVyj(yR(o zq{(TnNOLhzkp@|YkmkcAMVkFdsx)D6I6|7=HY?IJQ(oQVD`BcM>Dagz(wq!Y!Om~S z+RY{$X^na;LOBT_qQDL8x5MxgmytTetRh2|AM5{xStOK21~`tHU%X;@{2i%yhfaUC3T?&KLwn$vQYgtO_$x(u z!B%Gcat{4RDO>U74C7|7Q`cUSqrxOP6@N53KV#!&=JTHw^o7lA<9}>4Esu) ziGu$?`~6KgF%rhI&vl~4M7H)^3~iRkj-ESB&nGBHG=dNE|c~*?5I^(By4VhFFv;4xjj_KBFXo<(`kB>k`=d^U3sZGCOxZgYNWW zF&AR!GYKs7!Vo$zKv^}_YXC8FURusO`N}} zX(diFNU~WNE-c{%)X#a7@XamVT6$d<8`9O1{3!z1w>FO_Fe}_oo3XFH?MU5xnfrHf z^o6Hb(swiT!$6)_wsZ@R9D*l@LCsD3;#q>D5E;z?F>P=&vY)P1YwSi+L3Y;^lZwx}w@tDlA}^iB44RX_g(y!KF-F)GY-jAwC|taR2! zHuh4SPpk_wm0Q`yOZ~j4*8V?lu&bBG`uyHq@D`}F{jodCsJ4w44A?!x=0DAj%mi&Xs-wuFyg{vS1^XBe*bAPZ98j#0U z|7iCZfPOa|_hNl6w`{iIbyDo|PFKIK90hBkk@#UFU;R04&({6XRbS!;TfFu;HM3v; zi1h!Zn^TQ}iW;lBv4}sdw7`vTx~j9ro#`e8D)v>;3=T(3Y69&+przWDs#%d6d;~P2 zbNEKK>CdIK*CMv-My!ux11WYaODVgAn(sECrU!fd`cT?Tsr7x&rS{zogugdZ{|f#3 zWzo`akxSh|JoAz+ByjD`zWxykA$9p^6qVwQ-B{*LTOdWTI3OV1uiqbVRw@%o>fZd{ z-X!sd!R-zjxN?e@IFuvFR&Pw%J*0iNFamDklviyZB9BxvMp;an1WZeBmT_%}f58}M zwku902H9&~VSBDkq7%n3(;xjj>C2?}dD!+2F5BG9?964OPp_`383=of>&pJToEl!4 zHSl=vL71>*Kd%1f3|D_A;_kxGpJwZqfFE8`=pN1-KZT?(h?0tbR>yR?Ev31ZmIT^+ za8i5;oC!9>H2DJdl&b)z_Jb(HL3vQE!kkp}!@doCHK(oFq?&p3y#RKx#%L-F5G%d` z>0*=M6iGlb5w0}b8o+$6SZQb^i@y>_R|T-#D@pX_0JiN)44o6eKF81G0Cpcg;{sUB zRT~`?z-C;XM4#HQ_uN%?LVx#X7k`eSKln4RUt;J5e-@9QGyW{+mwxn!KePWbhkn9Y z#INU~!l*iDRJJLQYl%~y)ezYXm(FsSH5vG@hME;p1mR}VF{ zbt^MK&iZ;B_vtFt!Bv)<9nCRgC-Uiaq!_jez2PJQ_DQR-n8nv~oa&F@vjRv$*EgX= zke|3b7(%rqyN%&qfy8PE zL4)V1RL47fNW%HZKoZrqhQg1x@Q|;7p|Y(BWg;hUCm~0ZqvRdi6U$U#eE1uI#GL-k zC{o-Fgr``L_fI5>2QTR$70(6E^N>C$A3JuPA23)Wo^RLhSES7HRp1Gj@3fA)2a$+Q zmL>vH?CyPwHu)Z^fS=79x)$)hO~At9=C6krOVeYL$|K&OMjmA(ouBy=g{~Uk0*%XP;MDjsJeOeoQHy{= zi+4We;FM?kxdiIV)}XpBL=8!nNbG7@h(vok+uB*_nY z;iRPWLJej`kLrbM6eT78rcJFoSN>4 zXLynZO|LYOHrzV|ES_o4O(7)47U}}+i|4F+59>Sg5&CvhFbCMruj9#KBqMKF6HbIt z|Bj=yP8I)%XBVR`|9cf<7bj9tagmaI6hg&YCHZ~W=<_ks`;M@R-dT(Dd(~hcddhuL z)*XG1kjH()i6{NE6E}quo6viuV*R>C)?ege{Y8dSA6^&^>tB=UV*RaD>mS*^vGs3r zk>pMBto8|J!4Iszn(^Pl(I@9H{#}htSbq`PIQwKNo;B+)7uJtH=|bDK=QCQ8B-;!Z zz^C!7nSTQzVgB#1hs}SifQ9*YTqhaE%^IbW_svj#_ozEeo z^=aa%+e9*ejw?R6Xd+1>)cY=Xg3 zT~8d}kzbxfR(P+LG4^%3v$sZhmhti*;lzt3lVLHJzpUr$kR&>kE%xKRf)HMBA>@j( zNP$MXW*F3wdrcv8=pdOdnnD&^w^r8k^)Bti$t>}H9uuDDet2;$rv?&B%L$Leum7&KSW1C=Ej3~OgA>R0wS10&*vQKV_ZvuiLMX5DB%Pvc zu3%mAGm`Oc5T2PziS;MFWxnG{(wgt z)O=FS3GcP%ce;=W8nTv~;z*M3NKe6Sp#6O)ZeI~npH#OX{$d;nH~qQ`HCP*Wc#xeJ zFc>6k_K4W@@AiCG9I*~FW0q^q_mgWdU`ll4?0sy3-Sl`2afX}~$-$aDI4+Mx%FX+CZ6NzXkrS2F`YnMvWNJSQH9dq??+%d(1iE(Q8gdLcB ziF7UB>W;On0Q=20(1W(PncCvP;%0Yn?OfcPh4xJsH=XrZ+|0{Fy;$5_NBbpCfh|qZ z89up%1<>!Q;hm0d{>($O^ebr}jv=jpr92_xFpXKca9@ zI&|8+1i`B~-G2Oj{Yar*v9=cl{zP)5(8Mb2vX_;0&u&nMw(e>8YnTeM_CRZ1-q9_b z@9RpITT{d`gtijfO-4Fss2Ceb0;iSY$ncJ>Iv7xZJvW-?bR+R}Tr}Uvca+bBKuUoD_HSboR?+}#ul znA`ecZHw_U?Ijm&vljcq{{N=qABMW>n974*YN})J;~I#vwp=lW2C~kV4Se5e1jT#t z#4oR`9hip85wn5Kc+N+nBl7jFq8xYgMEUD@&O*6}TMnHttze|ZM*AM*_m08`@4N7> z^j^M6zNPcPSuGF1y36+%qPw!VWRg!|HM|OKZllcMF_^FHL0VcjVQK7?GH z-xmrn+Sk3r`z67)3+M1fNyI`I%;8&-h}CajwCWg_p^eyRVMX5u=GE%-_Uk$w*6*k? zQ4|x#+wk!}c;JEn*6Of$zZ0u7JFAdmIsi+t%(DL-*kc;rQ8sElx>R;+P zE4m%RJNGBO+MkAOLfHmw@Fs*t*(L~X6QdWSxSUkh% zm6K^8pM`F1PBbxWf5j%^iW%baPIApEBN-Z1e zSvD4tpS}Gw{peRdHiG8T_pB_rHl4m{Wh-i9yq~LAk6>hhU);b8BERzSk<=J58hk6e zJs7ZJ@aEy1qHrb|D1Uq<^QtrXEJTr{-3Fa)WpQ=Mlz++Q)Wy)U6>L+TrP&arO@Q6J zitsi5dNZ&1gLt#ry3X`%cNTMJqyBT8s${3`tfFJxS?1jX`jg__@7`eV?Fh5NRR}He z@F-fTpM?^BEsD<7XNadMW~_3Y|7)1On|O1WY1Ck)Cn^HuS6(H>o=7phhT_0Jk^V>} zuWl3)v;w38BL&DW0mikr=HgxS*6%Aw@l`wvn#0+Z`+4+-)-1Pvp2x?CL}kW7e43e> z*BQt#{SFi;bkm)5>z0EqZr6J4X-t;`(nF_4;>^_Z}?_Puw&2!Zg5DSsg73)8!JB zwRCA?rWfH|5Uc~S8%z1o5!A%XD`*S;A8(RJYt1~fIVgN-=9im;!bvkIOom#}C9V`c z#7P3EMWJA9LcvF)@G2-Qaiy@%2Naf@xzQICo;LGszMwEdP{3_nFW90hg~weeY> zvb^;QzuJP#qb)Ggv(gx&9qq)x|0fRYI&|v5Cz$lh$h2TnLBOO~3;n0=S~2cVA^Me*bS63l;XNrLH!Fzy}!%L!P+lOo7i{$@MU ztW~ACA__4>I1f*|4P#=_lcabsm~l=wY*GAlJJK?(((un9%r&ICXj+nit8wqwOhluT zlH4L#H8$s5q6-=${+HWI0)bR4XGyZp6Qp>;6Feq{m||L^Ug-I+h5c|3_p!2igk<5R zlr}Cik4a1Tj2L2#@>Adg?bVQ+V9rp0T?I+6ZXS7}7ucughSA?Hvxu*9>4ivTcghG4 z)^LHC9>2_UN0SKOV^~-e{%S1{y|#q#PAxFidUrJGK*N6GUyp`nK1t?2V@Qmj>z&_E zpTw-Zq66uy=Wq3L_vfp}5g+dNBuR;x7J+?iZHKD_$+-otcakX6wmC|)ZI0{+zTio8 zMrH)x_9RIsz4#wbl1};_5xA+Ge-Jrh$zGkF_Zmn1url=cI1=gC8d!v{yIqLXbFt{~ zu_TJWIgX@ILj=D#j>L@ntECj^diPprP=a(wjE;1t_DjkWe0+6wpzXcAqI zbo0Ue>7P)i-k%=uqMz|QY}RH&459NZe^tcuE!m70P4sL_w&KMhF&_e=={DaXQKl)u zxy`q?rLxVpqa}--Z;V1j!WBu2a>;tg=*E|LVnK1bx{R0yj25cF>Yut7L(V{ zcoJt6h_9w^tY!s*|bBFuMRx@Kfg28A_8`51O1nlm0!Kak15!uQiDz#-9s(HS9YcfC`;- z>&bE!_oFw%n0;|gjVqWd1?;>QG`|2!xdj}qBUX7yt@|o8PtG?5Dymwm>9UJIE%L~trHtN?( z93DfI`}*E4_0+^xtcZxXi|u}K4ywkz_Fyy?!2ZI!1Mg-Cay^uNyuwPG=d<5d*t}H@ zgvc-c2x`4nj%=;4sT{Ks7mW;d&qbv87qGANUA3EBiX+Et-^vcwodT!mP!z63Va?B~ z?nSv%HQPd&`znjy8-g8lfjH8iDRSe4RUJq>_ROlTbW{-AxXNO48rHGx@wojEtloY| zqi0P+!oJ%P4PwrB>n0;_^l8{wgEQ3T4LEEWMm|hb!6m z7C~^WV6zn1?goM7X1K3V_(biFt@Nx^P|?fLOxzDp#pohroBLV^zuqpgSwvy^YYBPn zQJ7k&4%!s$OsG|q;oBJEa7YR~sIU}q)~n!Va#x`WsW(%gY?1)%~tV2QSl86@7D zRe~M&U;AccIcXTbWIb$hu|Us*Wv#GE(mazzlF>P7$j z6ndwg3*>I1K#Va>eIJLgMQdhc+C!j4*w_Jp%|Scyycf?i@mz}jz5$JAWAm^?msyMN z`~*%#`4s$B;Sxx;B<&Z+|Dy%!lPPuLS@h((5N0c~q^|;M(L|u+KsiD*8t|2UWuqh%7WF?SQ4i;A?Hjpm` zX{nELu(*v2r7%2;gT+d>YGzOhE^=OSZb0FCO?Vf2Yaw6}gnodK&V$7{AZG(PIb;wAn>w~>*w*dZT-w(Q z@M<2U-T^{*$|+6`gY}dfc6-TJPBv4{`il=oAmHGTO9=a*xJ{=K$@nh!~!y#c-f4 zg?3W@sP860V$Ic7YOc0Yakbhpe&3harS%K+E6xF57Vk`b{n=U`CsKn)q8*Ln8$8Ce z6^=X{W2h=kyRy|^y|VQWBeQIX5s|-A$rQlU6)@$1tW`o*T-?|Y;b+4z=vD0z@2J+x zAK_LEE8fsq-|v#>?hUi_eg42huh*Z|Cw+^DcV7>unJ=-^uUqsfU*i4R>z!j;DPctI z=}RGjy6-n_deXzT>7Rp zuNv6IcZe2WM3}~H6Oo{bZ%MdDrP-jaT+GIvne$@yvm##lR`d==WC}rK8gssWKfb{g z{J%^jA3}?JR#k&+bx=rNrA-Qz-=2@F87TZ;jc22AEa0x=Q#pz@wE&Ziky;EKZT}x| zWB~`h=Bv@lQ}TvK8gnK9MTAiZxkRi5AS6Cp=gNR^?Q>Bs?u|5s7hO9Ybs}mB4PWns zkEkFo7~l&{vv!+&#apTZ zrDAb0O?*&AU=Y?Q4o&@jtDXzRzBQl4ZH_g52C$o`5+K6TMAT>V*}TmWv;tqG*lh7X z2nc86Q)s+sK0CcRBJUlg7)KGcpt@bW!(@Fl%Q*+orq;0uFv{mlkXSlDr1Lt;oHjfX z1NC_k$1rHmVTd}(z6D%k!Se+CVI2kA?s_)4BuE6eBJ-zOaFf)HflHXrir`j(erg)r z@uCGo=R{V;zFq}p0(gsX>(c(xLEn(gWyKA;Fcs{(H+gfy-RQ_vVoj>Yo>=1+;kwd zJV^~s&fs?=HX8qQzjyn@-|j$9H>a~AVG)5x?wFGh<*x_n}ZN#u&j_?Z}6qliPgUY%EH2>fRY6ZYD>qyP#b-NADxbs zt*{&X&*>z|$J?ci=MA1TgIN5fhBhyv&HUPX*ZGVYX!HAZzGVgup?rUxUz&lH=P#~v z|CuC-esrA=nThv9*ZHEEfP3dU-y_~P15UiJz0QrZ@V@jq?>CE#)$e}6Dd&+{WE>rS zottK3IjkS5XA_Gq>_x&OW3UylYBtID352B!1(Q8=kF4>mw{5-WQ2^@gB zIg6XI$T!92>}ZH4mJ|*6t?|WK0$;;QV?kuC9`7uCVRW7s&ex@rXn7?*hdy}f)P!lC z-Yc_6qb$d5Un^V`Z#IiL5nlf^ew z6dWb(6&zxq7pP@Cb?o{yFTn-c8XQPx2l6E}2} z-7$hbjtWz9aiNVZXq)V8n-Hr=XTbm$-y>59>ID&e_z`do+No$O8=due_u4DBloj9s zDzHfMlK|jwYGYp$21*_y&2n}1)cd`NB;W@ zBm^CC9>sqn=Or}%0bXO&pvD__3faM(mE$4Gb8%;dg~fmuK~5=KqFRm(WzJ2%xIrZF z-pnKTC?~-ZJH`2Z?o&-;_1%%x^OR~DH5r*hrIZqZ+x3zx?#`WGfMA2$*;P8sTwu^& z;(Z5PrZ{zvds_0#N!@O=oKLH-xY#CCQ`Vd72%j!HvmOWtQb zHs}Yu$nRIv(frJOtgY|vCn#YT9++S7ggZ4XAj7Ec8Xvm=gO2*)j)y4^IYE)FBtkCz zmvmNm{hMRNA*^ekFQ*c&6$jW0+$80U5AyjUGgwgIv&0T(kllBzD=d+#0Q(=TA*kmI zi2NPi5ugH+m-`skcSoo@iq_tm~i+kkY1b9TnLi z<+3JH253^=MjrXFr1%Ej7{2-?9NwGf%kB6z%>;+8l9@EglIHS@FG0Cuf9Ln{YZ(K$ z$bbiuRO?kqq9I8uNMcbW>F0Omu?JnX&BNJMQJN5uiV#{?JrKgbi4dEBTpY)GSb!jV zheohOz7JT}uDXMFSApKWrgqh*&o$|)Uw(7#s@6Z_ixjS1^}HtFVF6l*yBNAsgAh>=G4aIeM0 z+@oAN)lE)?gT0P5{afhhNE~Fof$$<$qi!l|Gca)%Bx2Uxel(9=i4c10SH5~NI`(FB zzH2dQhuf^zy2;r-Dtja2}$x-Ek8;woh;5O;;7jujw3>C@*1=uyqnTk6G&*p$@sca_>8jC zq8u)RA6feIs1uIj3gEF?Tjog9$>_>rq1`QLa~r8owuBw;aYl*;_UKpANQsRT%$Pn=pPGpSyze2)JgBvdEXP3SxtE7UmzA zsha=K&4l^4>fXfof5ASntMMZoH9{ebzxD~$_)q?<8vluA!uZ>Je$-vAg6W@pLN)#O znl+eyQG=;!rr#k`HT_M^RMWq3^#>$6@?^|9=a-Qe`bp&Mt=d!yhehX zJBvY}@(E$%y?wDm@xZ`)JRuCcZJs8tX5K}T#=RgO-ycOAD-cI$2%Xv1`H8t-V zsj+#hI&*1<17Y2?b{(DO{f*Wr34|1bgvp;nnX9dT&S$TNt>5$dds{C=6JhHg%~WlD z0^WtKm&|Nz>kDuIP1yRznX0XGz%{k?-CnA#FPy2`dWn~6>l?gOTYvScV(TN9gP*^% zb;NGP)<@1F#Y4dZ<|()=C3d%k9hv2KQy<<9pX-Gk@AA{S5biCL0ptn(giN~9m*C=M z%=r4ER(yt>CY)7H5%|S}ycnXMAfX3(mhfT}jq&1N<7|VzmB3XrTpz-RttEOo{tC}r zOZvHA1l)xg4c}nDjkHJXnPdH@;cD!kp5hzq`ky?3AWQ7_cj)cjSN+U*{s?6UylkfH z4tTc_jd#HLh7IIMo?V;fMw0Ryl#lI`Pip0Nh_MkS3gBA(-j$f-guH>cs_#^Z$ooloWCh8F5vv` z!7rOh4(&b`|1JVK&<_f!w3W0{{F#8cHch#a*Qo4gl!^Jj^H!b{*Xs)I0QD&hz^V2kDRyck-8;;!fx-H=MDtD*tZ7CCmky`i$>T4WIG38+=A*FPxg`8|`7@AGasF zj2i)N#s;hC_$Y0Ib)6eu(SgMCgfYaAUrQnSI0qPT-U6tdhIolv0CRC}VhT)UvvxHD zuCvk{C8oZZcD3i$RE#FqvU%-!Mk=v1D$8xp7dI^%-=6PDCF^}$X>OgyGi_vuI-;;P z?Yvh!ek!(ikVcAI_50j#ybaR0UZU~Ddln=U%Q4~@&?UI7=xO|_4XabP^xT?;<(z?| zcxD=jF;Xa7gj+SOQoqOfwVtm}Bbh#@F)wg>iV8iylSZt8imAG6#MVy{9<3jol4TT+ z?+5?#mP@ORdcL3^N$%XV)fZ?b7G!S>b;Io2z3i_-A}ikrz!!D0#p$$?2r?iB^I)83 zNU3Xwv<)joMd{{1**1S_?N#VJy);@*#j{x7@bANK^&=4-uAsl#CH9oB;y3;Io^oo7 zS2v1!eV@jMzSc~GMWpx>BOk(um%q|oS@=41D>1nbu($2N?>DFM`glFSD#{W0hWSuG zulCw3>Hbt))3NYcM!Yj~G01O&OG0W71Yy8BrMNjm=mT)j|bjP4} z-sShkyXYz5P{dZqB_t#5bNSd}l1>-p@@>T=!sv(LBXHM8N{LmGf<>c!b}s)Kbuo#k zbNEW{SKz2Y6(%jBZWhY+i)|N(;ygcfPRA|lNUWu&fCr3NqiBie`c@>d3Y!O)TB+y$ z2jucO>xd;whq`L5OnmI+67I&`ht*Xz>swZhp(=3vhW8t2t1Qd|#nvM^ z53~seQTC~`teaK_eE(9*D$T$2R@>tK@Chf}6!BedtWVld_@NW9Bv}Exgs6VV3793U z!2k=vH905TTos`pyvqq!q-gsvs7$EzrvH%zpSMK!jRR_>vQ_ zulTewG=p5@1!vh?Dx6?&j_!0!xtij-PXW0?8%!aZl&N97bGhk*S$|6Tgv!~!Z zVvSD9vn%1CwYQuKtFO@+V&LK`+s#juS75=s{nRN5>7LD2reMKbf$IP`gm`gwRe6_u zl?8I;dAW~V3IYvvUpAM`uCO0@EB_)}LwzmkDgNbxhJrVn%g0?CjP!2&{;f}AgsYm= zcWAE6KO69c`!;T0iGx$nN<+OAB;#DUOF>^hxzv?`UOsZRYyFKT1V{QdmM8@XUE!xR zZ;bCnKV>7Xfq^Bya$q9@=kbwRbOSG+Pr{92S|B3UKrA0PW2B89j2%Mab#xBllZGS6 z{&NIhKb*uHN8_IYLTD(rVQWI*X)rBgDAAztb7`~bNc zL?=qERp;qwD_g!~X zd-E~)mr8>1FO|RqrKb+sO2{Nif1SwfTaf(MPUJpYNkqUD2{R7aN8VBBUkd{+@=T54 zeYTR8K}%cX>moYcSw|~n6}`wDl_W3Xv$v8b=_e+BW-Bpv@`G1*xJlh2$4Rpd`N+gO zFE@#clRI?&wGZJvuHZF>7wY5^pdIc+k9Wj#1^qyQK9G-ji}a`KO?=B+*u5&7$S=PI zKBt1ucHpxNd|m;3%<*&3kWZ(neCKJgBzVmGo+^XF~#Mcqs%3uL? z`*lIJr9!IyxR{EI+KBT-Atw|0Pj8cdcqq-Y5)ZE2Mkt|jZ@y+b=}5oH;YYWVSVdEw zso>!IIQ-i^(3-ge$G>IPCTL_UO;bAjyK5Q;gL&c(GJ$RgI;q^EF` zY5&k}WtfsFtXx`ySSZ-R^4=EQ2do-}m2sRZsTq_az6DxWohSC?!tF zMj45DBrj{qNE_odi^@xhPJhbL4ckgJ?f z*0kEe|EV9f^g&&Hng^S?+-$2romA0Y_D7l6UK0c2CIoP{sq#pvyE{P*@W@~r%2ixJ z_8SupCci_x2uV6P@Le*BkWRdGCz(Kca?UTvYpTJ9)czkth)HeFpG2wgev~F#8iuwe+buI+yPJ#!KfmsV#rnob#aFS^ znSP^wf2lZBFMz)jN^Xxrj5G|d+ckO|zxjTVh+(SCi ze};13y(G%_ni#&$e@$hjSsde=jTOC=j*2(Qh9Cd(DSj0H#0tseUG|ec?a!e@h0DY# zHRT^|vEX7OcB_gWT&nC3F{D0Er=e`Go^mAb2~B zH#_K*b4N9H*^rH{isDHJvDW$fc)s=^!N0g3#*ZB&?daV=e)S+RKak%na;9gt{6m1gQa7<&RloKBW9+-*qbj<; z@10wA(|ZreZh8nMkU$dBLoZ6TAteEnCIW&YqL5IesqB^D@xez8q7Nikf|M(wk^myu z2qGXw2}KC-C?FyrCGU6c-Aw||^L&2qAN$!mXJ*dKoS8Xu=FFKhN@Zh4bK(4SvwpOw z{T@vpZxMUT4r}j7YTP1*`qUZy>x|wPO$nch2ib4K>CUHOr@JGUL{rgL@kRE_aQb?y z7$X+bZ(GIIJsn(R--&(Nd|Ny1#59QWK*mM)F*pXXLGy!#)fLsZX;Q1K$Gs{8<{Cp- zs^5Q%VI5vt2u*P)@@TNj<%23`L;Big63MfAUhiZuCQxgEV%BSy1V zhtjSZv7PjMZ;>uOEO(G+BB|lAiwbJRFa5B>N^Qa@S*qc_ zYHebAWo2Wh%IjU3_6Zi*1|Z|>{C!mTEfmSsRxy=Eek=gr>T0Cd3_-g9^ z(b&Jx*v)r0woVMO7<5_Hp{c!fB87~{G~(?|>e8aUTa5O;>TNXCNl)b4yAKUL5lVmT zgPRvHp1XSJ`!MSGgV^Z30sSyK(4Ij!2xWZ`lujFn&#l z(0lx0hgNj;M{%9_7_B-W+G0=z!?9Ov2RK}j_uln%#3gAR(Ty*bfF-cz&k5K1`Ys+qHi;%s{1ka+DsDwahHeiF}$ zPtl~q&WcTg&!zvPVkzf>;qzDeDW|@FY3^D)IDy3u-Vxwhy|J+_xw*P<($s;B>K+W% zqmF=Ci8JVdqax14=6z%Q87O(4<}3_gdIcCGt0aOz;FU=5~CC&kIuc{r2d z){4ug9D@??lo-ek1ki)0uy!*lJ0)iRM`dtg-Qdw&8Sa;zpYM#K6Q{%hsk~{Uxnl)L z3}({|{?h>WdFS9dZ>=Qmjg^HRRTbf=Qj;zEC;4^VYi-4+a_zfVI{yD^CF|5bd2 z&lrd{ovHtqQm`lQ%!KQQ>;~Mn} zr12NTXPQ%bHKn}J-&I;6wf(oavN?@=Q=0Wu`_7u9iz)6+#gxzsS0JWVTo$cVaYdZwO!%ib_bxPL1{%9Zr7xE|ur8wX z{eNOL-$=?;aM()fa8^?QWB&yCmiB3y@W-v{Gq z)>Y_HS4GkrSH;#*wUL?!^5xrwsYc!tk(w96M!q-W$!8>M_1a&e;yo!|`wln^_=0%K z2V776OYFwHeraeV8zvqQ8 zBQ~_iUy1J;xZ!;VDT{%atB{kMz!d;b<6>)H-U1ZZ4&@;Lq-*CP3w$xXaTPzrGeL;S#sv<-9N z7c;N9>N9SNSJc`t<U;S*QBqIxOd{d3@s3 zSxYi$mdN7FMy?iF2W;C8h%DQE>KStf)2$!PE@#+gG1fM?MgDA8el3}5-&X_3!I+N| z4P)`F>lyl*v8)uM9i~Uq;Hnq;m^+QmP=KVPfGiM_pG$CpCZC~p63b)ZXXr_ZbzvT7 zs7hi{OadZ_Z5Mx_mt{6q{DiK`Y%=@juQXeiVwZnjU?GRXY~o^Cudu%CnP2IS!n%n6 zq%4&UlHt-ii*U6k zCr$v^<{ZMs_!cZ?nZ3NtM?Nrx9M-n&XreoFj<#j)ESdE@O`p267f@MFSDUxV;`gRL$qa6%RDxH?n(z76xF3C%X7Gs`O;- zBfi9aco&+j_^vm{Wi>DFiYNO{TtKy6u)#Gkd9gxy+$mT=G#$Uq8O}3d8ge6lo3s}3bI{8A zv?dj~kzjsmlSbPJ4@qy*XdB^v9h)@dMtJ8v1&&F(yFu@ExEo()hh}^!oXm^Tn^fcm z!t%7c3us6;HRL(|Vkp^s*+!)XH|OeU-*q{JF8Q)_3z&`3HGN+4@1ALm!_3i<`nBNxSxtiuSoa_z-;y}8U`^O$YQ zhrk%zqgm=GM3_q*Us7!#%lF#aBKvys3PPbj-&1JcAQTEO*1S;IPX)2a2uF)tFXG#| zw(>&hs~}9@=TFd?AXbKLFScC`iLl;93#_ZM$s>%}JvvzpnZsz(>R`~R@C5x3%+mY~ zN#7KQ*Mgp0(hmt?Gn?8^A*{D}n@)s)A)TV$p)8HFr%*Qgo`UQ-yrB4|d>LWj4gaKl z!7PGGQG@?cP%EknV{OD|cmWX<8qQL~M%Oon7={eEKT<2;SQ~f1IQfPfrLzI`^jbI@ z6kUjmxTVhJG6Ubm9wwVITCp#KEDTd{@W96H>JU68vS zhwGJs>ydOiinU=Kj+1{hdx`}frx&AHJ7ztuZ;oczFn&tE+1LzF=P^6}X4B7h7MoIm z?h|T?l8DU!<&532n{vOD{r-X=144Evy(5JC1&+GQjK;(2ddqr2`Sby;$Cn963R)Vx= zP%D0!5nP~7Xhy7wyay1+4V;ZU^?3%1IRY5h_1}}8*2S}2|5+%|s0a$>6`Aof{TuUT$eN!^aSG@C% zHn$`FsLt9mI0pNk-b`iD;x76;mAx&#MZ-H_#eId|>;T}4^mzx?&Aqq_F1mx26y%df zM;7B>mZ=$<+ciSvBEYS+xs>0LJ;M4Qp_Lus9WMO{scEbW{Wy~4(DP}`#=MWvTWKim zEM=v$eEHB}EMx^`;A1P&A-15`F45X_7HNT{grmsE`9u?4WKQ~6pF&McyD6#P+U5r#w{{!@;&x)Za7@&W`K zKTgHQvtHJ=gRODw)X<5I8DhlNc=MyBs#9&m@_WnZb;HuxNK=mkUErOXBbMJ=X3h1+ zAvd$d@(4jN%dP0lf)eYqwbdwcbdA7yuw#Cy%#Cx6C2KS;mvgPJ(e`7VS*h9F6CO>? zt%VPPji_XKjHl7uMIF~(Pf~@9O@M7WnUBtIZf*#wwV5}lB7=>Qjiy;MSyJeK6t9O8_&DDs9)CZYmMoD!j$vc4j~I8vsy@ZwSbu|u%QL3VUdJU4U3GX z76@=!LN%S0z}K?a6TU{rt@75~ZXdTAo$!1X%X}D6hgDQH(XHTv6HDO$Gn(s>?(X6f z6NDif0GoEw?Ba1~bHfB7V=G{@(8c4NUCh%3qRmEIJiD+^a||VQVM!LF9E_ody0CwU z^XYOIcFjwKKNkTa8)pUA=xR0_Db~{iIjqQn4Yi_mJ3(*du<-V%Y~4^PS3_}iyf`Z+ zD2n+Z06zh~k4;~D+-xU#7juc-!kO>BQSJCPOU)6pUqGD}w=OFT$jy0X?OF-W!oSxTMR zLJ-EAUmKHNetFQ^m)?KMS|DseeX6Yw2(+v#=vc?4@(n-{dh0-Q`wGy$wbH}a4JzO2 z%G!kTKCl*gHOGpE?ODu04-jj!qV!l>qBV)M>?eQl0VU6wNrX&WTp%7&%FjWU$W z8<5zY#f$IIechSPrXL`+2W#yyp0@{m)wsirpDEL@9?Uvt)I9}0gfK4eZsNDuHy&+9E$hkR%^CAaPjeXnV(tb@s2Typ zblZve5)cpJy`O9!khOTDiMYXq7(CEGT!6PaIbzNOF*7(1w01Esxf)fr`5Bm>0p^V^ z%)@%2$_D1Lfmyxv|Akp}VWzixv1F41c*2EO^l_j&j3a7;0`)*wz=z-Nckas?ceFA6 zDkyOM-ip>Vp=+w>w^{Iti;gg`WcJ2vG6wsY-mGW9B>@&|T|1lHoIe8C;Q)Qnn?25+ z_>mI&u%gx~@1@af-(XnLav3KH$c(K6;J82$7{|k)NcsVKwGV48UZ&6cK=eCHzxIKQ z5paNl`?A*2CXF(25xC%nP0T-t|ExWN&Raq7<( z&1!>|H?i=+wBlNRc?ez-g5&j|A^ASQVoCb_W%la zWRoz}16Yv%e|8cb8o&yJK0=8zft?#2*P{M>cT`1f2eLef$4?Ao53>nB>$?WBD3Rs- zKxYQA@0s-n+B_KX|In`vX4^#ZC4JKaY>mjqAJs=Z#EvjFwvM_Cg@WwSBl>eg*@q(3 zILX5xD%a}chp`9|++@LUwx5mMOG8JnsP;=Ri24ka4Ndh+_iH`Uel#Pe=qAh6W+X`#0Urn;A$dTRqqC)v@5X)*SB*n}5jKta)0%vML2 zVrU4Zs&=j;&X{m!G#B}b1ckG!>iPAmu9vVN#@P4t{b)8jfB4Z%&l~ub3m)HG z;q4*}TwixZENDi=N&Bh`{z!`oLHc{i1z&JCXSC6iDGY7C>r9+5jQ@*9(2`r7-73w>I6(!skpe;o`CKd*0 z+*R|0RZCW;ytjB|^mhe+6vGp^IUWOO!vxmDdn$Y)tdX3>d68uz8^u2JqlpvQV$9^KEYW*@@tm79%8hQ^+K?#SGNA)1gVMuqh_`Nw&ZY6noRUC)pzb zoxU+Wm(;+%-@snsMIn<}a#TDb8js>))N!%$I(Bf02n(PcmrPrILn9`$JZBl+`s&H- zb7nEJ*H~%nQ|x~CHgHhID_ieF+n!>rV$GWRXy?I;`BKkMqfcUHoRZwDjJQ%CYJ3WF zKlN)0p2lKW;@8w=8tV~-wZvhs@YQ;V|9NrJ`)mEJX)IP^WdZt*XIN*(Rt4)fpM}PU z+1u!8&#^u#qG(Pjdxa1+U=t7c`U&@g~NuLF#9gLe;y0>wzo(Z zvWuRX$KDbz=|S_Eh4~mOdPS}_ii?@Wew6Ye3rjSBarq{&6fVy&hb|nkp!f4t06iuc;D=gl>H;OTz)`T@4hF;zdI`RrsLUBmB3?ilb z4*GBzM8rlqyo{08@$INpg-N9Y^n!z36j#zDjZO1-VS8f;x(fnB0A0}7eQfM@>hdZJ zXT{rbMV3|hXCrGEN^m`@ow{B3U(S_>P{Nk86!9l|x|~h++g{s9=1s6rE5H&qXtXyw^C|#Q?@l0^I5_< zZj}u^g&W9LZDczoYVX7F8QH4g8C{p&X3u)a)$l^3WVtg?fD9{QO5tOOKe(h0a8 z5Yq~`cloz1SpVu1^k`Gefym~Vn_HlHZi-pZ97EY#S(XI_I*N*eXx3Ji?Ct*vI>9i)fUfN6^FQDH4xCYI5@ zTGlmo%I3z9|Mv92gywvdv7PO)bOK=fYu)LnuL#@C9T<^*o9WdZtSDCCD8OIb(aM&7 z`TyS3R5V@N!S-;$XeUaBLijI6U$gne;;H$JmZo6I@Sd4yNU(`@{^$TH0ltW!O8?W zdWdDpm=B?P$WQD&k*kjnvlKR~n$91_QS!8EazDa)v@fY{q*UN2#(d%meUk_wS_zom z=Yjkpr<=h$dVx6Bl2Dp+g!N`!tLf__I3viY*8e`jmPl;KM%&)>JcRg<7apAw{L;C(CBL>~r*i)>Cy(H1PQ(z``NXc+Gq~AJ)Gi>og zYV|Ajt?yFzUs*XTWOVdbb_W0Yjx)?%WQC%>_beMFd7pqoYw(5%T;k|0QT_#1k{9qk z)Fw8Qzk1@k9==MiV5{VXZ`V4k;=2ZLt{1X6;hY}}@6#_ASjUY1n0auJr)m7rIl!&H z1veJ?3pWM;?z=rg>x%!;#Sxrfjw1Mt>xTdN72(wL-|PUd{BKa%{|mN6tbLl1#1>}k zwd|sa2{!4@3J<0TCv$kFEnBWgsGuB>pAhQjoxqScDA zQoQ)XikGEF#jPvONfF%sNt7Os#Lg?q=ur_1`6+j^_hPtAgB5(CD0L7Q(iTw~$tM4c z!kHA##{G*rGbx)5x9HQD^oPpF@>n-1Oq3sZ7bnT7{Un?IuDcW{GRwR4sfRR({jr*& zeq{-64XgPu2&&pjwH{IcVd+nWwN9C*lp=nuf8Z&FCbKdtebq_&++ycFQ5;1}JEO$1 zP+HSjvL)3ei?DT0%&$yBtkoW^bw>~O;;Pv1!Zq$7&G;T3P8T~%!OR{`mJBJT{TnG};}PjAL%w`u$Y&L~w2 z(^Bwl#giZnQ2F4e?Gdq|;F||mjaNm}g$!wscUkLZnB7i&Go|pnw&5DrdKtL(gf`Wz z2xGUYjFRRW^O?e@nUQ`=7_H8fMtGlSt5v`VD2Y>~unqZSNge$GgJL}E9(Yg_fhT84 z3CtQnlqDTxz7hK5E|Ra5tJ`I*%*}xlF zVs{EjBCJSR<=U>oK5i#>0&(^VJ1t);ErNZN9h?=042xqVGgn~@wXc-20?r{>a#@UK zpE>Tj8`y5LJ%wgfO0B(d2)ZZ%S}a}!98GPgls*ow#hn|mCKr17TyEB4q!-)KtSad- z%M~P?wmpu{R!RSg@ypXL>=3kd*fB1_0O$i`eCN0}#aU;uqyEu4>2(IP$}*YyekdiG zUo$?Gj>**r=gRcZM^d?5T~zE&7eA7MGSC`yM@KFGV}834TWuaLNZ0Hw!=-6jtCnG* z6J=LRFYtq$YH6BSrMF!#`7oC794wsC2?5U$Os#_Xn=h$Me2#wDAiXLdn+c)Zk)sCD z3mc^jaksu{qqI$A56`4$HcK(A|4drBSt??AGwGMjQajdhCVA`9lPq{9$8|qrGwFL> zdJVSbFX&PTJ^zW+jf*#*NK3i!zeP$DS5Vm&=^A_JS&I5x3RVU_+ep7HpY&5A>+vjo z@u_q^)&r2W@chsVcl9gq;00&0e55NpC05}@-hnhHfQ8AoW}vDSQ&hZcxK*-=zf-Hv zq=>MyGa6}J54?bm)u6Z!vR|FOzX($s8l=ypST4MOCS{9zX#Ho>M833rE`@}xMIMfN zt#^>~c@OhhF;w|;DTUDtlTeP&rTI})P%2+$i|2|Of1ZrXRbrO8Y>l5m9lrpTif7P+ zUq~Hsi_xf3zyDFC9!8ZsbAge&OZ>C{_O+B6X9;|5oAkQu!&_H(8mDF(w}FV)=*BiF zf?axso*cu%{mwn(EE$pwC(f@_SOemsbv05nKfuGE@9t+BL-;sdg%@5hj_YV=jWkUB zfb6wWzW64U)Jm~(Inu!15szfOQ!91h77?{lG<)V5x>GAHVS}I1mu#03MR(ZxoW_uw zUlBuFcSr--A5WVy(%GkZr$re)hG^JMsTcbeF}tJ$aXWptQwrghbUUTd{N}C0T9U*q zo`WpL;H`ko=9kiNaUSjY5+%-hn$CZTfi>Z2YPUB#yQ z4SW;Vglu0+k?is5dfwO4TVa0klXve;VbF9+>hE!8Qe((=u!W+E*3|Q~)C#lWvD1?7 zw{en79x=DFmDKiE=^>Bu7Ri_WDt+fa2I*REc^{cXPo9zP_vq0g;a6v*RxD={ojD`z z^7n1Z0H4o%%1oj!&Pu@+S0#>~l^)~$2!2B#)#UN+lBH)JDSp0bL4AcQ zQsp=Q|1r$_Tqy7H#oZV_%8+;Z$(QEWbfOu(<$nDjxFu*^wg}}(qSw-V!Fs_~x@hHG zY>PNN9dP5jA|7OMt4c+Y|zyYAliA%=>;y7$v8%RcZR8 zqvUuu3#f)ukv96miE=kc2N(CH>w723Pf4spXT9rG`9YESW$JG{C4cMg>F6*wM|)QU zQ?AR_r@bKiDzYQ_M6SMYuG}`1^(vs1Z^_}|g$3AUTr4z}!}=?QP0L|+0ez2nmR_K% zZ^*Aotbe|dLF`5QR>~o)DBq0F&ZqNl$+KBRzCPh?IZE_8oQGWrtRgsn*{iRpkk?6; z65h~)wtCNZ*QGRFS@-> z?kfJO7rrkKYvpfiqjkfOpI_Qu>w*7WLMnZeA)Z@!g>u~4W~_$@_i)wI_!wQ$_L7}3dDOwZp7 z8nH@Pu(jm6;fhp7DXSE z7mMHMmB-|sBAeM>|Kn%5M3$@V#d-A5NqImdcpY~r6IOKsm(v?x70ThMKCp<7#ey!h zLf$jRdQ}QZLOCj&oVv$lV$t%o2ji`ThNfxn3=1~aky)64Fash}- zr~i@%vVR6p#x>lvc8QBHdrbPCNsgcwhl_lqs#o}{$x@0P$D6Hpb8 z0WnU+<|)P8*?F8$jfz$QdBaCS<$3IAQPFDqkT`8LDm)s9F|8cCP~pe&1Z^zh&OQ-G zjgk@*KE=1Gk-QN$G}54Iu|nCh5?^SLvn<-^+(ijiW4(R*j$7rTKEe%jF7`UnT18iJ zU#}(bD2o2$qqdA&B!iRiuKJEv$;$31t+V!8jFk@w?HuDoPf= z?4T$)?M}#AGWK|VfV|JD6s;G&dBJPviTirapdR-6B?S^~jW zi{WPL5+1E*{o?h1sfxF3L)JPdq&B%JFJ!q%LOOSQ>89jnarYsZ9d-1hyE2?rr0HoM ziWS!Z`JOM|Q*p>RMslb9p33vMn}@yOU@s-k{F>#Zq|2A4A>9Tq9?R3EdGj0`_LaA? zGxSnXjp-YSAF4gL2rLTo&|2$8dwrD9z)N<4AG-?L%!SSvds9p?KSCC?CtWeMR=Vk< zq(VzD#QJE#+ZZ0H4|!L=#HNf?ziP0_$CtlltDJA ziPJH<1#RCW=vQcZYeXSEjR~8Kir!PeGCvgX+&ze%F$?gYd=GqL47K)G2BN~)_0I8c zQDJXqg$?m?>x=ZHukxUO>OI-pIMK%61GmS}pa7)W4X$D#(| zzzw~M5ml{s3sm-_7mI4#^@w2Q5{tW3RNx6gDxm7`1$cuNBrB@-Fv3?{VI*xIrbLRq zmx^p2+FBR5)I)zXT=|pr!n(mv!#%*B+^c?_Z(zat!;jS6t4_PZ0yk=KtNPg$uJJPT zc!yo#VlSOqDS;Bu!N`~=6(ObgAsS*nUMt||VEjzn&ESF_fM5A9aK(kL)LXw|QwA~% za#mwuqrS0<-QN~<_m!`pD1COUf)g{S58{+jVwhuEOs-bEecSa4tbLI{CNQBBpIwxi zpd`YS{G*L;38J48Q zKxrz#z~zlJX$K2K3P+ z@CR&`lay$2H*HE%(!{NFE=gG_*NukKcVV*9QEYd(wbm!-?UmvresMglYp*0H%E%EN zDLhpOM==|uR@c|=5cciiUIfroex1drO_@KvovMUUV5;(P+L7?Pr~N^Mxg*~HnOh7n za&zWUZ7&U=ZK;ag@AG@GY|$^LDpy2{QQnCF@=3A;lbELT>=t`Z%4meG&kN;4kl0)S2S zpgE%ovdrNfNd4252h6dKbIWz<%FkxrmpUm)o<`oIiQlEr zyZh(g6rZVV_51uDFm_d$O01LK!4#3DPYz~!zP+FF)#4~FsZO&GniM|wq0x;+K;68)zdUSrk0HM;XMJV;nQNo;P zLTO@-GSdtcgwcf@#cl>{;S`Vyo{rPFT;)?tFQGk2c}j_ACTAKKd*0}Te|<`xQY>1~ zw+^8uo(|~}Qq5Vb5dXo{< zx1yz8mD#K&jXb(3G46$JwAR1|hC~_Nlqe>q(L>#o_(V))2cOCl@M7@!M70vV=twS% z()wVmp9AOW4W5u}??|h=DP3BxPu9+*sFjV`!j0ab^SLX+Oe1~mJ?Vkm(p|}852sL1 z{CoRFK*QaI^KIa6L(97>_eb3g(^?zlsb+b&wAk2PNnp3yQDP6}%zwZO?9>(T&iAITuxlsh znfFv?%rsRUjW})qW5p4u!B`C~=^K5Nr&zM0`}9>j8H6V>R*$|C55_xtNB z2Pqk1N53$wapN8GpLaw*v(x#0@%SOxVs5| z-ksVHQ-bCg2qL-pVL;ViNVK~tq1B1Nj4Q$*o`5)B(}u3XjbOCI$h+H&KL>cUAYA@a zDq9)kih~s)$6N1=yN0+>SDcm0@By@AnBo^}AbQ^bRQ=>kd=rTyU5V@6>Dn-*(yXmP z)5xm#kZ>w~22I!anzenO(>tZvw1W6TFG`20~u>!lpPk6Q9u) zkyYaW@6r_K>IxAGpAmdv;MLmgLEABk;ZCi4XKIePzb$`hjTN!!L_8_0olZM^bNd=+QwG(kDQESQ-N zy8vC_BxMf^IP1=zC>E-)1aD%9DJspO{!^5fEnx^`b_D-#O$QlI98c z2QK&;V>CgcOx5>KS6aztb8I>KwP%$dl|XE|vJ7qZ!Y73CljwY|>^eSM`M}@b!UZIp zS2(v6-WGamjgMFW26{zp#-mv^+I#pAm$n<0v9Stav(=muuvIhepM_~a?G!K{$*6# zwn)j0#3;p8vjEKGMC~LtbvtiiE4`!lmPo+$>5G(lF|$~PdjGa1!=U<9lj_l;+XZ2r zFhoEy0p51GhT~&AeN z6C%-b%OG8x*V{UjN16X%c6WS#Mk`;1NY<0lr>`m#LfY_n3_q^!gd4W@rDg9a z;q<_AWn!q}OyMd)L^uEghJ4p3HvRf?Wu6#REx4RXV4!Wtzc?Aon6^aq4&w_l&zZ}+l(!)w7$%P;GGYnA#Z5 z`sH=XI+0&c|3JB7Il(23f(|-;sFa9is6Le%KLP_aqQG&MS1XS(mhm^evJtGY!{6k; zL3y>E*WY)j6g<}?SZl*3j^9bb%ai3jFk`O5Uoh9b^LpT1`Um9U=fWEye8CgWMkOTi z+Z%W2*_(|Ut(H*daciVe>s^5JC+UFMQ3U1pHyf2?ew$_^s0KCqCS|ZlG;@;@%iF;J zz&181J=wGyy8CA3agl}Hpr>@D9rL=OzoTP20rLm@7UgZ8Zi|x0W?iTATNE6@U#E7T zD&f-T>vw4K7#0>b3?Ez`5pkK5SNmZj98{G;m$xWz5cH|y>pd7S0r7le*84hr_^A@% zUzn>|8%?eicNRz8UZaKYj2XkT%hXDeZ!~1XY!wUH^pA zl6zJ#QY8hL=xtqS_19Q_L;lpC`$oA6SzoBg)Te!~9Ah@DKV1x;4Cfwd%2_QS=XSmp zA?M_MN};$|U%yZJk-6`7!r|{?*^f$=*PhED=^B%yuz&thiS_!NgEp9;4Wt}U&a&q& z>%SjRhKl~lh;zLKk->z{_RBQ%5O!$Zmucl8C@!G>&7oO8DZjf{z+EgVFuyp5rX5zE zMNDZfT|BI`^`3qS_}xwX6E0EfBT8Gu*5uHmN0jHGUarVCZ9I`=(Ga2BYzFck0ozAo zbM^j5l^iw(n-_2GH~3cvr5wVup=NuFy$zogA;_2{)?{J9DCc@FEF+HA`@*z})j5^W zoIv}I%VeVkt!hm!wDVEd*Pasgjpw>Drxo39K9uY}bn$0w#4p)xzU1?Z66)*dQy6V* z_r6AapTa=O_(kdE<*<(l(u%+$J(KXji0d5^mDc{E1hJw#ecLaJFE(5D8m8|*uDpxS zqI!vDolrWm!glo03FSi;8cZWkDlz`MgEa}w;m01kP{ghRrY}FK;LUIxFiQHm(@K&U zS675r5jqbtC{tHt%g4}h2a|WJ>fnNv=IhsfRe~kv8$v$kuzSx5(U+Y=aU8JYg3`fq z0!m7IP6*w+pj-|)i9nGpL|cwww?rz)GQyD|y7Zee90Q-nW`@w%-M?RMnJT^NY zcl`JS;vAe|PZ8uTav$Jl!PN{{g$d(a&IlXF8T{mwKZ_Dp73j)~BPT9> zn0eea57)QN&G4*Xzy&LWggIfx`nuhPu$b?>P%8 zRA?(xq49~Oi~Rqu2#ST{ZT9a7oL{Q1cs8fkwow^_$GTKmjklbRFs@}&>H{p0rpRg- zN3c{@hjIjG`9BbJRn+_Czaq3Mx~wAOT1EXwi{Qhmx`L;^sHz`!ZXKefVO0DDiX23a zTloLy*$C|#{;w6qYJcN@=)4H+I{rf`QoDiwto9*1ZxA(D)FAe7q~2&zM~RFgX|$XA z95Cz0-Bf?EWs7gRt3wmIHlvGx`rs;1Z8{U7-CX^RQLdGb69Hv4;iwRsUvgQG4B;9$gniw|vw$ zIbVCjSDnpnMNovFnh+yI8eC)$6rsiE8#|4`+%+nK>kCFj(BGr|)EJ&`A^%5s9r7_b zlJ@&y+|L6Nl1U){y?PYb{}0%1N1 zP#b!qmBN@5|c-E^F2Yta)^hnh>5Dsnr6<6lZx&@u1J@AdK$; zk#s0XZO4R2vIL|3sUUfI?hjLtBKyEa&z$Np^!iyp)-HeidSa4t1@FEXhuPw2Z>YM2JsC=mhN(|FClfEkHJKX1)ObEu zeZoQeQrxHrSEJaXNP09Jw6}%O>TuA=H;%4^tI3`-oaR}fTmMC=ql5a$PqSQ!yfm*Yo)Hr;BB&(y;wPtMpXd@PVIXPNQO>hV; zdNVN+(*fR|IPQ0TbK*vCjw8{o1~TA28m&&?H0WtF$Kyns`e4k)$fogdJOUW*SPTr# z{&WcF?^8DPC-R5bK{NDkh8;9SzmB#857vN%b~VA-uLePke*M<2#>Z4dYOBy>crhq1 zJ!JpiAJ+gbV0P>7g<6Gj+jz!r&M$*_= zb(|Ffn!h%zNLZe~A(sA*RmbwyjgCVK%$8+wYL6B<_2Y4>H}l5=zZzl>cU$o;U*K!t zh$lhq%#KCs8Hp;M@VhkM7NE~cQmgqIRN$qzZ>xq&bFk1L8{`7P%vSHIy%Q_$TZOH{ zoqVivg0$2fgY+F^dzo+OAYKOC2$ypC$*pQJ!sCQyGe#p0a@IV+jjGuAnK-{mY(A;S z2fYD@nqagmf{Px$17a&+fl#@-ydc2RA1sxdkv!BU9WiEVTG8H)YLC{wQ6?2@TvWv71BVbNu$AcxD)7tqwZLcpcNFEP zVf5Eo?XXlhBL=G+TX87OOHpN*{D@*O2-k4d|7@=2LR$#&$B}8k>jXz8hdYXj zqqH)>mzZ!I<-+kIhu1_IzVPO|;M1LOTeOjWcIF%dQME8V+lk1o)nYb1>&ozY7ZWbn zjal}T3x3*(s5Dwzg^E4_xKSV;*miY&yxAD&Xxf6Gg;Yhk!u8QkmJ(34INX&HRNyUM z&=j_&zrOB%HOn%`D8QL+M`ve&2K8XggS=nd1v4qS1u#&sx`|RXcBAE2 zJ2~MlO4(uzN?mlpU6d+~G18ywgwq=Xk&9Bcc!N@>Tp3)Hs);iw^|J}b79-E3ASzmd zE;{)U>AMBh^pmxTsK(Y_w`Znsa3SR zQ|_wdJQutyrKys$0c%;w=MbjUl`uj$U9679G4`r9djAqNRZPERJ;BjQO>KU|g$@=9 zE#WI%D22APVHEbGL4g!78uDIPAoU!L?IpsiN2>{iP1SB|RC{ShXES{R%x2bbE&&GM zg1_X1+uCV`Xy%-b^kJbAN-<;9tt>E{j*o$qW(y*Z$FR3Sc>iNqB)SEW&*SPzuCu!G zxcWQ(^;2V2m5F8g`SI#USfgZmW1>2R8-l^F(-Z0^ki^G_X?wV7$kSo8{|PR2+l%q! z*d*-p9M%`YsOu!Po2@RnBu(Q_u%AnjD!GN|?K`-zAqp8-K#cTjCaJ~9xhRZ0o>T`! z;&eVt+m1zr%Tc8<1(jAW!7rmLUwFjiZ~M1=QGSMzw^2Ry9~;{RixhWyqkkQVa)!a!Q{v|1EX7-%RZ)-LP_ zc~9DR2`edhD?AJa^05HP3J&L=QSb2bJZ7jd_mmez{bs1SEel;f!z^_F40U#1C)g6g zT!tSAom&k%`FVm-*zYK0Hwv*j3vXCx#x($b5`tryAtI*f%br!g_F(t7(jT3#wqh1c zEew`)n)4#Y(~ltGLhQLg_=O8G&RT@$EkgXUFq*a)qy_QUELPiE79%sK|Ix)5tf0ST z3HB(UfBPjM2I${^iHaA#!syTvGn2;u1n2Klb1qBL?|0=E3Qsk*+vO z*I!Z}kP_zu_x#dyZL}1&v>ryurc0vWs+=U#NZE+5PuJ5N=vvGAPfq-essCo z*|W>4F50<#ZuW(94pe|ksP(WG9mhH7iB4K?6v~ecn&V*Y!sALh>wPQKQtL1%*7=DC zf0`$t$}L7HABE^5Ap@|mD(hWg?qv(E)m^aS3^0#?s_}Mbo*Fa!m@90{q{K=Lq-4AH zJ;uQIGb8oEmFjtsWyS0H>(tI7cWiZT2N$QaD;usDHfeRq9sIFf$$`nCsO{lash4dC z=T>5LakVSlob%iCdBzCi_uA2zI%`=LZF^tsILFY^1J_+?feWLN<1o_JcG1RzDBJ~< z^8}#U)b1l+EKi5@cjZUfM*ci!S((~m#G zGtXajzqMbq|6+t=3cKGH=D*|ZR@!x7vM3LX5fh_Wr04wwa_Eyr{NnAo{6F?(dg~)K zqf33ZG2Z$@(}uppu>cQ?RfTb-gSy@W6T{)m2(V(L6H2pnpKA5A6zLG^;Z=%fh2*gc z>q9AYPR=m-Y*a&&j2JHdRW!$-5K|<4qZy|6->5EPKTT?M+( zoCBa;gYa}tCI)pQswBc+>ivLm8%_2Vh+Z+3+1D3iKj<*s=5CK4NSLps*~9E2)c7Y4R)Ucr|i5kQ_oS3{$F3Jc5Gmg!`!e3RDFhAf5LuTKP8%8-v#9~Sc5?QzfzOg?QOdEesnff z?@>MdUfRg35oBCco{MjRw7qHwo!+CyizW2d0rg3iyN$dLs=v^~->AcwbtCmTq$bd@ zZ?HT8<;`!@u;3g6NkG*O)Rx~9;x!O9QtNNkQ#_5&cWPTW+|2z>?aI6(HZ&LLw}D>S zt9DU)VJHcY(f51RXW)LMd!5=>6gATJsYOvxpyMvVYOyltNaH3e9~)pdMj4|8?Mu46 zPsKwpy7Gf+5ykzw*M1b?wPt;D5pUA)1JH{(n-cJuj;3@GS?qe=j0b}sF_M}_ey*Cs zIq0`Cj@%qC$%l}-unMIdmpf>itP<}&L7U+2NBVOf{1cdR8&+nR7_M9N{K~9Nk&DAMoPs^RMPKVXZA)q zx4z%=ee*o<&dge~=KsuEv-h4ulRvijlzvxdxy9%iQgTE5;1aHZAH|(Qd#&UejHg#m zS*92x-=>*0mPHg(Z)xTaX1}pShJ2^h1UDQM(uE)o(0UjdR~B z-GAERXYBgX{u}w?Ni?4A8D1>C_dCmYgE4x4>8|gwj~I<*rKf+e>@|Ac`N|FEd9ToO zXDlxnhnJS#eAaT8fj_orvN(FbT6|+}z7D@WH}NI>Im;aiMlUR`o9N%?ER$rQ;U+q9 z4z{q9k{L?f&ReF+fPF08ab9Pu7+bpSyya!XP$yrayL0@HICPmR>c!>bU*DvQ|Cm?Rr`C;iDt{K|2N|f51R6`Wr^QY$V6X#a-A7^ zW9RO<_tAYfRv#*O-{LkP!fW$W-8xnu)Z1(G69{Xo4~OZe3zkWK!JQ?ASJMWQ+| zxU;y1UYmnDi$gfDn|Nkaw}8^;S}b>2l&R3w`U?YH`rY!6j==qwEMq$Y2QHy~!3O1e z3jKD;@+4o_(`K1&sw}!j0q>Z48s4RE+AIOiZ#pf9aaYhgmn~Cl4}i+wURL1yF7!vq zv;s`XD|isMx`>8d!Qu7dBD(8}WwL^$E>~SLn6_WB^pyD&3@$x%#WKU7jRZkTyJa?C z0^5!WiciAZEyK+bSWce{+iY!-CJ%`WFnQLw{HzT;uv&vqa-5 zKi;Wcea$kv$K2i5=q?Nd*1o0!r|+ht*DQ+$jzPR14!u|d<9AwyAlx=k;C^ZG#sJpN zAYj&Y%lv^oK}c{4@N)`qNBA=4Q)k9Q*DXs1w(im;_Hjx)hwyLsft5~-&rVS`7>|TJ zdq`Pe3>i~uGbnNRJWO3Oa&r^j$4|y?Ax^$m`hZbsb%%DF7)Wco;xdh;JLxu0WeH+3 z$5E-L5)WU*c(QdFsU`UKQL)`+F+A@WRp0-IP9t-^l6(z-J*|%6P+Rx|>6| zwb4sCjl>1xX<>H-PpA8fFxuT+2{zYESQbWKc2|BjM!rNxdnhAq6JEMTygk^vJKFnK%S_(NKEtcjy{9tXR=DFD{SLlF*={(aoj?nFD!u#Wfxwq?H9aHmYH1+6 zPN&_~f)%(Y3WWP5dMZA~tQ~X#b?EmXQZy}$xLj3>XEclX?QzxleiXlww0;L&!>dG& z8VmsKy>}11bc8z-9iDrd);eD+Ma8ha4K!`uE`zTD^U%qcIfYjD!?!TEZKtRDDZ`Ajw$t1Flo_}=vZL|-d~;-f zULv^helS26MWqoIcmOmi08;vIr`rOQX?|YFrs)=~Gw0nXulsh|AD|4fmhf+#_uqwA zJ6kST!g~Mm;*ACJH~94};2e#xE7ylR3o3?hZZ*oKQ4hBu%uAylZZ?W%78mpk6pDBw z0_%vVxEZg2L|kUeko$xm+2VoFWu{SXf5pd|>;BHH%darlh~mqO&;VLEM48{i9fDcKFu;uA z$!d9l-W{U&b-$kf=lH91Ziq5~n`bb$)*AP9!#7*m{_H=z^syiX7c|uHS21UYDz&(v z0cGLe?*T)}&{wUV5KLG8LkZWvm*-?t-(gX0B3e`8}`kok>@No zcli!O1hr{VAM&FEqm|xNGhDd^&wMKUC?Hr#kUmGSGO726+ipnu2!4IM9;S7}l~H6K zp#F+%B#YFK4+48evtO0@Uam} zJ+f;UiLW~q9A8a~7)3irDua7D4Qd$M;CEgk#{+A}DEfA!5)3Ob(P#4!oD#xJC*2fI zvwk8@r-Jrp@1V5wh2IOx|qufABMP z<;u2IDAAlF7@?yS{~)Ka--NHmIDg~oiiBftDQEWQ3rNv)c%vW zQTvkb7^TnOu&o*Lol+u@E*S~27KZ4<6Ec>KfZ_R@MC%J@MFpE z@b~KE_v_^E*U3MilYelB-_hbVtRv9kHL{a`Oeg=iPX3!a`6qYsPwV8L*~verlYed} z|84AdXf{O@-1zt_osw3Gi> zC;um%{GUcRZVaL?IuX9^~C zS||U^PX0Na{Bv*k9bUKH2zV{%Hdi(?CZb;JySbZav2gk_#iOvB$W|jVyNPBsyxvn( zTm2EA+r^_8wzdcJWOWUM^y038kkG5PYY+&Tp1#$dBHz=u%v0b;L5 zJMm^H|5T;kY(`5@iAl@JsNu&DvTa=Jq-mWkIG(#0<%X` zFGGb{t?y~ba`OOZg_}o3FGH@yBfpm+-{Rfg)6j0=_%hYI4ic=HhMJy+Z1)Hus@y$F zdKzlo+qjq>UYR`&C0)Jqd<<1xJ=(nuS)Lx1Jqw5_M1$;+dt zmm#}5GgWr?sOo8G>k){;71#n%lqy>wiq&EZ1W%r~Hws$f?Va1xQ048N)6>x4?Tu9B zK8Xds^uiQnXsPFPrJJGj@mp}GBE2wI8AelXQT%EAY$b#4N3isRxyoy%(x-1z9`8dx z{#WTib1IYxl<}jok+%Mb;Jyl_XKB~9$}A()L?KFR)+=^HY1;!zh=GD1QwGvw87U9@>)f?#mdCEWce#P4Zcxs4nVqzJP1?#8E0^DAc;=)UKM+87AiypFnb)b1=fWLkq%6sgy9Qpm@GscuyP9W1A0xxWK;(zB6>RXWMIuL z(4l}qw+c}KOaRsZQ&EZffr_ZQ8|4SK1KSzb;IYdfMZ~8Hkp#>ErU7f#V>JN=rK6&Q z6=Barg@EeALWBVevZ0d$V{)+=w8JCvgoqrXh~{lVBmyg6fGqq- zp1^7$DuHDu&_uwD8X?+%abH33P(^s05+Vc`dKxta7JMs22C%IG1q8-?kEIlt-iQ_h z`kp}#4^xD>NeEwH+BuXHSoo6=(ZJfDg-8WD%Kr-i@MPfC?h;@)-X5<8w&ShxCZN|J z5Hws7<<}qp*mNCz46MNGeTl%hE(VbSO!qY4vkerahd~qr)B3^84Mt1g^1T9}V8b0) zGXmie=$cUok5C*U0iFtu7-tZTz!qQ|Fl>rJ_>M#v=5qqDavBl>Ga|tUjJnkzibkQp z3k)J91cUAlgUA7f-i3Hz+Co?>!05XTqM5^s3_=~Ph~gy%;SaPY8ARAiB zD%Ti9GB9baL8JqHA4QFTY5y?@uQ3?Sc?RKe6Pk1@1OOAZ@dZ+d&qsP-w1e%)+q8=D}&LG->5$Dm8<1jdXMwbD% zTto$d?Y|g=BO4z3e+?oJSbqryJ`=FVRC4?kgQx|TwL=iF=9)p+@riCAUUZKGMw^Wy z8<=4+ieg}!f^S`cVfZvxgn=Iz2u#Lz-(^7j1hZ%cru8)n`vkPeD5FCp-wZ*cjUo?N zf$L8ifH4zsRRj<}Br3#22#CO|%fNWtQWp#inPC(Wz#v=#mk2aR8ASmQKT#)2fGP8g zq8gaJ9O=W+61dzx3fQ_9AD{!X?*kvuJI!GfRq*7lH;PtZNxD(^PC|kW$O!14V-(@Q z>MceQ53Jv26lp-;7f@he^ovGO4$Rq(f&&{0kl|#sz)MEq4Xi3OiZEdIF0>dhs>mo( zf$CnP$N?5O4j4rdJX_u{ib`O`n?_LwOn3`T1x$Gx0;izl@1a0I^G6T>EIDBm8Ne-d zs5vm>G@2e5{4FZN^d_`S1p5AGbPcfeA_@ph#OGJdz>@#qhRLaz|7lxHSclO!&zgiC zs6J;B5x{0(A~1qXA_eG`XA;@KR$w78`gxP60QznDBn|>IicF#on7Y>_)aj_vD<4q$Op#Mn?)Hg@f)+KcED41+ANxY@eRm$ z7Mk#kS@;6$o6I5vSaZQFqJZHoW|08&{sjVoVXbD72~7O2Srh@Ye>aO7V6@^U+JNou zZX!4e^18Z-C}4)Cn@9jQbaxXOz-F79a2$k3__&E`U^%cJn9b6I|pMZ6d3~}$AKT1Gah_E?@7o97(Cfc zGy(&sxH*Kl1*3clG6EJY1|b?XTZRGvi<8`h*R3eXQ*I(>F2XOki6&s+i*BM7SOOID z(4^blgdJG9+f4)k6ZW}@c%Z%54Ql~f5SRfhc?EKS>H#-V0IV%>;Kv`~X?o2~GypRW zx``HGd?_-Hfq-%d21dN&CPIMqz;IxVFD~o?HukoNWMFvCSz9^?WNoP#$l6k*Dq>k%$^o*rRLKZ!$=@nso!SzR zwWWL@YfG&_)|SHEAqSZ4E=-9Vg}|?Enp!tO_vj)_c4$$JT|_KvQ6V0}5zA^+u7`+? z$%U=}WGyP9tB6g47L|?!tW9Nmidg>_pqz9SCf2H25oWC_uA7Kut*RPWwG&zx=)r|T zgn9}SYgvI_B9^tR3?OS+wLsRgg1d`Y*0M6XJ47t2S#>sK{0b8EKnB1hVD^3?3W3oF zP-37*3F2+S#Ohd;H)?(mYMHk%v0CQeQ^c}bmIh?CtQuJK9+Vv)5nEA(eXN%-)qEsG z7SQ)N=s?!ivK(N@_!v#(BTVWiP;h)v1E_EDKvv^~ALvlyqJbqR(E^B1#$j+f)4xP~ zZ((BfZVTwF-ZcUvzCo8Dp4GhYJ|dRYJiO%)+XgkS8t7E>`l13q2;m6w7bdSpA(DZt z_qBk)dS84$5nBh$Lp*uLXRp271|1V5otqKvn~5 zfUE|F^cS(^_~}307C|1FkMH@VUMw%n1-;g!5{($ zpvFLsZ*wz9@+woo`^8w+b0=B(lB9Sz0@NZbO#jEM0i*+EdjD(Dn^J{R!kFt-cU@r#;l-L zARG<_wE+THQ4Jd@Vw-^W;lh*=54{k0@J`49vI3h8IxDbMKvrObLJ)=mn+9YBwi@VQ z4K{c*rrUC;;J~_jWQHxk&{4t^o{R**8ek=`X(gZ02vg%Kq#J{RtVWH14Jptcf#LU} z#emH~|C@v<1`07(fE8okvB(FCaSAZ&K4-kcShpUkc_Vw-4{QNo_FfF4DZ-S$ z4_`L}tBMUG3)uXMEO6riR0v^K;UgkMZ0>tVhcK)1c?h#AZ+1+@p!*1_I57P<2GvwB zK&Nj5vTpAmi9z@=Y6uKJVGtqHuuee5FGHABe6JZ;ia$mA>1ct^U@ZZgfmJ|O{bN99 z)jto&s(%A8An8=??cV1TAQ7xUf-g?BDy5pKqd zL%0o?17zDGavo+CY>Rv#+ZOFWwk;B3Ajci5dm%jWK46@WwI9f%wFa2OVP9y_KsG*7 zZ^Nz#;qUM%*Ro2?=Pa1dRUWun7_{7GM>5+>PyYEd(zTvDxd4BJ*wxQdmbdK(>-{5$~O5 z6iq-jlHwO*jKN4MTa5jmtt78ROv8;RNTM)BqD$(55s#pWm!Rn$Lz4m7iZU<7Y=9M& z2xKcNc^RfHtf(R&TTx9wwxWWPup}3tAiym<(1J^`^x*x;fLQHM7Y^shSk0>$L>QImC!~-LM>A>b_7^=X?xiZ5T{2-ynKf#{}LBQyx zr~t5HwMmo%%TrClya9Vin&dAAMk1W?fD8wxqkssPJ2sj`6+EpE!qVM{f;=u6yq<#Poyd z?!6uRe+W!>7QiNa5+ZzI!m|sMXbjTAp}<@gpvAMPUkv^REzBl=Gs0~0hZkT>!Q{^X zvdLc$WRpL92c{`Z{tO_S{FOT}|5Mwx&3G~t_tS#S^)0EWL|5{^80)HlHZ%r2Dz z{oit;nNLZ=cVkmIjCl)8uS5&{3r+X|rX$e%D4HBt1muG7DM~%~_!K3w2xH?Tv<#3> zQM~s+=c`8F1NjuC5g2p=^S=ZFQfndLQLKDlqvVX=q9qs`(GtMubI9;9Y(^I_-S%QB z{vCpWeCpz{4~hv+T~dI2>H>2vmQP)Ri?NjZ<8%e-O8T0e1;tiDZ_EVY=m=0nMD{#%EmV_f7Ci78GJ;L$h%_7DDh8lSCfc{}-;q`B*(!dyC;RKW(m~=Ca zWPm{vLC?Wr1dIU|go6%@n*=&goecVu7@)uyV8#^Cf#DH&aPt(F^J!?6{USDTrdcE+ zTszl{{)eZ0o-A42e4HU69KFOW>`!AntNo`SO>VBH$Ym$23>S`g+#svHPx%a!rI z&)|?N7ktmlaL$WpU4%n-pdi4)S7iJ_U<1Npzu6(YHe-i-6^Bs3q}L?_pL#VyaNS!t z1w(wyJLs?fV5_Y#i+CWPhD9Dg6MhIf!j;EBe+E0`S2$GzsyHR91I7U3x1b`xLh$pc zStF27&4NpyPo75qXTZa!X7#}G@6gXkko-NG6j;^>!OvnGoRJ0NQ?=k%G4*h&mIiD% zj}`(w=_efD0qdG2UjwiS;l!WOBF{nDxFF;C6s{TR$}ggzh!1z*I4<}#s7Jq`Ai#q_ z{Kk$cwkk9+#4nmj5c^{mS&;5!K=5xPR zV1t)4-rNkV0Y9GuM!o?$&H=r)VsHW*5f1K&j1kTQvYdQiD#EF~+(ZeGj|+p}#QM+Y zg-LHh0L}~ZfqY(A3oPu5V>&RZI5&hd^Z8+LDK?e>H<1Qx0Y+^@jqErV1a1LxMtrV# z5cJIc$O!R#zSxLx!yw2*xN5+(dRh*7vGmIJQGXVz3mD4Gek#vtops2rOe; zU&g27V3HjlQ060^4=CG#d_bA-7M5omP?iJZ!`wt7(yKSSi6USkumM;Ggfq4SeP2Yr z;Rrhr!6%w=Z==a3qi=vX(G-n9KG5_(1VeE#G63>{=0PAIXto2RbEH5%*i0(NKC%@D zmJpo3O~&&H=$#62d`V<6ZT3zJ}Jd%S1g~DwgUO2H1vJ&y@IX+@=0km@F1`i>1s=G zQd^0A;58iGroqD}rq#gaH!zqgpvB|DH%?wcN5VFo4=9aL|_)eZNN%ka03bg%mIcT!}R(NbYQ~w z$QT&)0|xPNC^0{xBEYya$Pd_Z7W~z)|MJeEr0_(Y$DjkY0s}urfqufE0yg}NrUJ%X zL`FdWUocod!HReZ>44^T!~^56qp43|9T66h4=lFeEE=e)77<>9m97g8uYoB&Eus}z z4h%ji942!wi?c~XfC(qDl={eUx77oE_IZi-Ld}?0)nTX|6bB|ig0-TyBe~M8L zj6;}D&+~z~0Tz*mc)Q&q>VUOC`)61$`ddUIFk=Ac;}GT+c+}6q5NHt*z{U`Z$OV>6 zw1@^^?o^8i`vNOtq(x)`TV`5tg&JxUg>+wHcbg*%90iO*xH?*f%Wnlg!rn392W|n{ z>(J8pwmcQ+5o^Jtdw6o-X#m#7SwzrR==OOgH*j_82tz~<$sIWQ2viWOEbOckrNbiizcJyu(UqXM3Kc*Hm8>lBNK z0fyX*769h1LB_!3RAhV_Edu1x-wI4dI6X~yL$tw@^rR#N;;RKXb1vQlk7_`Tw;&-fCl7rOOy4H?ihwN$2j!zl zzk?uP3^3>gG&zTXB^-Vc72q(?>w65+?I;*9y8v>5l{*|@gh%WIBQUa1W)KJT`T;e1 zS%%YgSwvHJ%no3%4P#+9x@H*0KoJJrO=u}#7O)j~5E!+`A{v3-do9906a@gL<4}?x z<+K3#QBLyBu!EMq%iik1-o2q2|EkX&CjuJfQa{XgXj#unm|G z44RIn271j$fltT+Hv=2vF*a&YfIHC=C-E!^mh%xmk(gPj#&nzPF9$_i~HUjyf zQt&QJuLcZ~hf$;NoC3{p-=l_zZ)ulde%4fvaFYp-{?KI}W<1b(0tIG#5>4!eXHd|f znk|xErYNEz4_&R|q3H8i7w~MV{dMgB{E#Xi3PXuI5^Td@1hPPWXqANR)sBZ&9Oj2t z?bu!uJ)L1=gG6&+H)M!SDhAkEftCU?zu5~(qrUG$j_f#komBj85=rq3ukF zR3stYsj#B-pIxNuvFZ|2utyth%TlLy2}dcC@E6gojSj@AlT2Y=ZFDhCjSB4FRqKoh zknQ-(c9+7+;b*6Qc!5rk>O=S4uKL-EyGUxIBntJJ3$*=qb*wGQLlQ#tHeYywR&P^p z?Gp`7Z$t)nl?;h`O4|jRw?Lg_^X(=HS$e0O_}SSSMh^=W+<{;BX;`3|ZIM2b3lC$Q zPDSz)cc`O%%xH}`UrEIKZIXEEXPR;cS~^A};G#oGcwNe-7wO@WBKD#8;?Z)o6I^7TxIh=gm*1MXLWAk?rD`9aK*)(&;KK344UPa?!QGOY zRi&11v_AW~{X{2{)aACkB$*;o zCmcRcvzB8#B;F$lD1g(ckDaIOOz_Z(8>17ZpQqys)q&)wzBf;jw@ z4KdNURz1C+vTZ1y zPCK^*=C$L`Yn`kO=gm%Ce1?W6s}uTgfzt4olP(!b^y&^jL)TN)36!%=_2}EUK~l4H z>JL9&b1u1&p1DSvzg+cx?y72`2iB>5odeSALCIgN^Kbi+7An?$POc&MsUs-l09rBm zU$oz$PNs?%RkM2}O2KPt@T2s*L!D+RX8&U}Ia8e-_|a9ZKJkdO<1cZO%m5m;)2Z_s zdh7wSd~rptyafaa^XMtILD8p z;t%kiazloyx;Oq?3M(`6)E{Cpr5ov&9M#rE@KVhE7X1`i)~hr9Ib6o!%`!#4*4QG_ zvw&ijtG!iIlEEXO0I%Es^0;d2%{5lRll7eBZ$;SY$Z)UfYcp1Q1e6%!JjLm6KCAuw zi!bZ&wzqS`|D{c94Sh|?%a#Hvwe;%l?7@qh_A~?!$xyrZ z;o22~(yrC6qcc8ipzRsz2q!}`7(DW%m<|SVGE8-Llqqs+8+F^EjwZE6^)O{4G(1Zk zmCY!1OCK5I*-0od?7gPwKghUuMX`Rg+R#bGM5bcZXedP)D(4K z;0%5Xgf*uKB(&o%izHJx60lQGoTjyJV$9U1U@c32UQ!Em>Vebr?GEh8T-9p)6>OCZ z74WlDH=d?t_hNI2%$I~zJ>{&^wD>h>D4*V|jQABC%s8;Kd8>Jw7_3bO75G~I|Gkgbm_PhEi-Suk{^Ce z|Ne(MC;*9^t4b0u?tm;&$4<5FYu>5m`*7b?z9ESnb13#}IfuGC&`)(0s(1GYu=(Oo zluFh_-X49a|6S@ptG^bfZKJF1QiqxHN}bx_1gg19HJftFG!=0j-bMP;;(V}7$_vyt z=;L*~e@(Sz9g>7Po$z!W1teheY=2iv;lahhK$}%Zjs$gtA(dW9P>0ycj!AmQlzP8T zYIj*^pQ_`M$Ww-$`tLd#bvHDpN{vv{RU<4zcC1G~bvMRQ_*X76uh!AwyD_+TMsP7|K=o&O?f?1N)FTbE$9#NMV)6dZU zN7QN7&=|REMaVV4D@*lqs`6XFAAY@!p8f{Y;-6V+AEg#CMTmj6KZCqpP|ZppTCN!} zQ1>S&NeDEG%Tne4@r+AhdUtM%Aw_1fS1oH4_r9N`laH+xWR0;O8Dy zXW2s9B{fls6Y9Xv*_`M_cRr>D^kFq8A1h7HHOUpB%eYu8jhPMEs;5(zsAsP0lB-VV z`m&Z4wSlzWp^lWRdVZJ7H(J}d2^V#tty${KF1(f&;jbAS%kEcW0zdj*Yu+ft+VN)= zxDgsINEiRiXS|_cKf50d)1Xnq^f|NaGdYOoq+t+Om}FYK;^A~^0Mf?7kldMu2~g`M zsgb(mQ=hU%ILTIJaY?rQ(~e|)DfbbKb5;wjb?%a{onBpy0{!?;)yI^Fid_GvI@Vy zDI3-K3ip>Czg9#W(bQkzb<97lOgSF1U@}wEanS zD0ye&12AX9@B(0s=qm-))5$l~KsuSN_Az?(qYK&U3Tsn8No%0)o7Mib>2YKbGH68hu`^`C(=zSc^bh(g%$7j2h967&_Z^tf|Hq`ZHt zfwstCNlnt##S_Qr#J|VS3 zkfSc|T|QS5@QgqbY=25T?@1(Xjg>q&dzL)Mk8uN~20n;aVx4WR59`PfS;k=WB|G(= zW76E6`xFLl;AlzhSkZ?cVn%X-K>r?Moy+rH>1CU zrjYSJz`zI^1GIWgmjy_cTkJ#sQE@rV?f7LkSfH2s8Pwy5)s`3baYi+Z!s_ij491v8JQZw~&N7jt-=(Y%OyJ&OwZE~1%?!HZ}; zW5gob#Td7Uz5rSqmdFe$Xx$cG3Z7GY8IzaNEoP}C`0Gu(?LF$2hk+HiOcL63!m{^hdmav!8WB;OB#C)C@g^s61XX9K-tKl} z;LDlZLt~y-2N*-v(Sqk;{f({Gs>*upF&$H7^$}XU9ad$_^SrID)QYC7!#5qF zE?ZI6hEz#lO_H4&aD}NnfFPi4&8EA1rN2`ZBh42LdW^v^}}-8{bd`JkFRF7)F`F>`KZAM{vkAlT z`J-B4^yMsRlT2*a3p4y3?xP8|Foz@r>V%8s&dv*rM&1YU=bb4T^7L#=alr?>NY56E z*$Cs!R-pFvPk30e`RZ&>yRt1SK;L>~NwylD?Ur&rybhwz3e*Y4BIaiJP&Ez{x(<$7a$8S9O` zg#2DsCj>rJp;bQx8Qbw!r!jXNwEMipo9rOUe_0K)rEZhr&3Z*nmC?ekRy!%XxF24S z)E51icXt`h+l2{Iw_mG+J{}%>OWK&9@4`cg;1WrVFe86B^`5urssf=ycB`ZLqRP8= zqlRH`(o?%}%vM%PU+h+Ak9Y$gxHuQbL?p4}FX?qDrlWuEFVn|V36&I~3hRp0fwtT- z$<|?s1(ea^Jy>!-FM?GSeMnMU^^$&A$|ap-YblomHpbbh&y;eqmBzNibZn10Kk%(X zT6uVk+nJ?8rs!B#-+z;)?8WngTXjx-9;IlUZJY{DUHzt13y$uETHt#`%Bj?gH04bm zT0s=B52HKneY)_9I@y#`=`>ZwQq4Y?Urn=FIUHxqm_t2^vGtVCp=pcfO>o2j5oDXB|w@Tf90p7 zc)Y>kbn3v@sE>~|h)x~AyivcC)Czsvba{q~_?P#h?si?6D8+kDSU zf?X%9F5#lxYODK660&qrqe^%inqf2l?2^Y%2gv7j7`FZwXv6F30%O!K_;pitm9egs zCLhEWprQ)3A=MtB$Y-^X2O7uQa_RD6u=?&B++U<&Sp~Z7Z*`y!7BF&tq-$0My z$L@~3fk_tZO+DVk^6>ZpO*mT_cKpS4k;%jL@}DZ^(=#Xw9+D8M6Al;C0VYItm4pbL zu(OyhItiYV5T_F!E2dGUXo`q#lE51UJ9S<$Jywd*7ULxe9W%U7F|WWgY}q{|p+XmR zc3;Q&*KkTL!^5y9n+wa%&MY;|64ld%W$_J`Ar$-;c8h0=T^c*5mrRqVkI?IT`N>ug z{rfF6c2yrqZPlrV_tN3F)H`vj>|N^OTw_K)^xa^jGY9e>^fr5rE4)t)J$ zQRT1zvV-V}a?H=n;q>lj>P)%&zgpx{bq_6hjXwRJ-Yqw#HSb`TO&oQF4m^T~3k~l; zuZatx3-4fivX7QoCh%6|LvioosZ-==TJx?t&YGvuB5CS_P-sHVs&4f0yQ+^he~e5N zPxBM8?|C0q?bgDvGA@#K+{c0rLr}?BT5}l2!=PO*B~^z?X1t;5bn2*=Wl66bh9Oiw zQc^P{QK&vI)2IrV%D2C)$xe)v^45#ou^v6CL{igQ?L$ z?ni;)nKXy7A(Nh9%zB899mRT<`3U)a2rT#)t@;r0#gEe757pa@MUT<74>3Hdo{(kH zMnO^)MnTP!GHweG86PS{oH6ieI$EU;Hm3cDE>uD7D|m*6eWZ?aFL*}s=Hgn>=drP6 zeWdzZTb`4VakRM{hdCd7r1o()ZOWr#>J$^@N9`qiz26goO{&{$romz$zvd-|8aG=@!(4|_qf{6So9LDIgWwgv76pJ zj{Pri4;iab%KAC3SSxyd6_s^nn;B;m~mMb>D?Oic<66e@T-2- zG4w}1x*_7EYBqYc(#(@cmeMMd1C(kc&(ANApij#Yte*avZYf2MWY1S7w_=_@JrKi8Z>mqgVoM2C~@hWxu z5}sCg=CLQs1RnNynZfg=I>Q*&gL>6rWK{H^adjwdl8qkaFn)k?7l&i|)9;LJgK6eh zz@p*w9MBpca@Dz;H`2O3RxFKQV*)gX(zvggc8{bL(P%%s&hX~fD0|jQy6`pRCaogR zQ;?IkniieHnOjCGeZuIUMw9D#@;yMC7z@+sT}JaJx>m2wG&MP{()MNOm85UfAfs<4 zJ@pNw`bRrYjGj9UMXMPcd}2fq97;v=J42ZWSz9w@i7IG*E@bRIt@`0DJjwCgw_tD6 z0u;fajEAq%f&ExVGIMd9p2<-ye~PN$sH8_aaXr_7n7Ym}6oDvfbk?78Ue%!bS*!mX zx0mDcwR6CBX)2v*fT`sDFS^zM1+3u-TJRm$_8EHWJG5QRvviun9xqd`@6kr;URv-y zW@G#TdXX{uH9GS>=rx~HzaO{_zoSJzVD@JHK#%@_^an3;>-ka3530AZ<|0`d(E&-n z()va)w_Tw(8V2bVr+GiB%T4J@JC**Z-fqlsC(kqBDD$NiXVeu&FF*R^ z3{u8KlIK}qU2mFumM4OpHl0Or((QDVF>?TUHeoAH3~F}{oh*9jLCpDoHmQBAg<4#i z+`@1s=0-cUW)oq+fQn+)q9$Z zE0oW4BAa=$pH7RKk-lj}E{!IJboCewCE-l$Oxt)S*Hqm(lrOAW z=FzHChilZYm|Cq-+jQ#Lbu#UQ-$70KSf*v$mYuqDoh;wx-%+>VPb4+dNdwiPQ6FqZ z(N6!4qUF~}mRg-T96(O&cny>G~s| zZ`aC*NKagqxcN35>vy?=gM#$4vIKan=yd8nP0Fe($ix1Vq!#MbWou=ly>SH(oRfZ) z)DH7?_*yo$29oC=>M#nqieVN0n+waAYb48>tLhk=x26Df2zW%JvViB>k-k~uNYdx> zD2-!sJJL7(S4!`op1M~`2X&-RL>D}z*3_tu93Im+ki!_8-A8VHq55&aP51JntsvU? z2b!j}pQL)})Uzq_0Ou4_3kSQT-KJ3|UgKsRDXG!A-7zmko@#DmYSLIqZO}W%q*1Rj zwQ-`P*6GyJ)iUkE>!2nskkpPxFsoOyp+E3hPpco*Tt}OQ#Jg~e@8B3<6L(2s#}Z^( z?Htd~-f10TvoDmyJUJHds^lt3+yi31My$|@&uGNU)**chHH9iwf1Vb*N*`{y207do z8mxnCRe3UpEPp9QHLa3E`fY<1Px-!*)DnHTjatR;DhH9xh_q#AB(=j-y|j{UF+?Q8Ql zNNRyjow$;=^|1D%9VY9jehEfN?HGQ);kO&u;iTRaM@Jrk4Ph`_18nVzWZa@#l82J% zCbJcfJlWC*by4+UTO%j^*Dh*GTRdRPjm0G+cwPV@2eve#D=er@d^zM>c zpr<{oQFkyk+FMdPULSbm9_nMUj`m6Q#sPm%7veG}5y#iPTnN*hgb|c$v8uN0!IE02 zH`Bm-XrIM8!`3`RHb}>o@zV;~_Wcy=FkALeO{m^1yI1gQk~3@>!zH2Pz-;vjdR;+# zB?n7FlAdDx3O){>WXl*O3Hf>nlofP~3Q=BK2^#gr_-wg+K73fU_O>;J$YdSM!}jI$ zlZuQE-Xsa-da||4`PjKPMO&>Nwy;o1tXsy}a?Y0pj)SLf^R1Gnf4$^Iz zwoG)zoU-4cl}Hvys6Q>GpSoHH`GshNaJ!_aA1;+uN}}#DYM*|HWo@qvD_ZaaQU)8{ z?9@AwxNGsMx+i8{(gsOQ(+lsD#E*vi&=**`ZMhpIwP1*r_J?Ki4UUj*)*xGcp`-@s zs=y_5N;hkKVD|-@ZXAPTcKj8;E;-Ys7<~AKT%1oUys(JZXw)2?`m{!U;X&2re36q! zy!Sz^EIL=LlMC9U7fPC+Hb0@p1m2UJda&B;_^h z4YzD5ufn$)3*MviJ*;z$*;RD24H$l$p0HVQ9C4i9c4B`vzQ>W>+o~GdkI^u1WTPHu z#EV!Q>3y8GdRqr`iub&&GmXv1$-O5qv6^n{X`K)_8_oKsvTV`Ha$}+`rUT%#d6dgS zc1+D#i>0CnyTFqIdReWu42`8hZ#W-~WqvO!bjf$5fR3H$>>_?8WrofFT}dd`lkHq2 zm#~Yyup|^5meh{#d)6-E=Ro+r=ZGY1(OYfeB7UV^d!1vukF|e~-1j6)s?PEoUEzm| zzxrS$^8Y{*^K|0-ck3^)yU|Qv>i}EMN0P&?b8NhuHu_@qOgbhB`Fe?`-_5U0^rEkP zQPB#Gnye@5b~kSde$=IDewOjIBbzK#W2{j9BCa)m9CM@^PN)?UVx?$mD( z1N9Lu$^g^u=)WTh3hS7mToZ9xVt)*c?MIa@aS9 zz6eHfTW_PmBM={UJFQ`?TR?A)z$6O1i~5ZOJ?1W2Gt#=q*qT6}Fjg<3k)seFw1hT| zLTQ7S$THOMTNwdVKZ+;U68arH*3_kv7Q>UO4<(0K{f(JR>Cq6R&s|1e08PHj|Dd%O zFnuCNBW22RS~MC{p%_1M%C3ly-TF}7Xe)N2l`^iGM)S(yHO3lfthr7 znT**_(R#+Zr)U>r(9`qni6 z#$i+Z*C=h+24M}f<1a-&9Dtvl8W2%>|2XTD)>5yBthIw2eECIZ$JfTP<7;Bs@wKq* zoR{VU`2tO6c$7r1@1*JaxHDFW<%s6*QnzaHPigTx5I+)r7k-C$1^O)~a3P3S|0W*S z-3l(UD?e_I5d;4s-W|+=e-VEL%9oWTK@i!dS|@eUuI3a&zgKACRO?vB&hKU2bRFp( z)S)j#4Y*Cl;|CI)&PNO5Ai?Qe>A@Pkn?`?53){5tw_13p7FJ`O@*P5Fm@gxo4ahtW zEv&sHBr3JArzT+S53+z!T6jL%l4-8-_o5BP{6+i*#QX47BCZK$g21njmT4J0s%7vK z^5afSyj^Cj7i>zS46oPtx}yd8vxzsg_{X$(e7Gh+5|e+F{LU6f{$jDSms|*l*Sn%r zORx!X>@XvoU&xL-BLyYNXn~tCMKAcbY4NTFuhI(6m0&mEEN($(&y)NQZVvte@W%vp zdVD1OKKSF(cXlT=fp#tO7cH#w{oU9q(c~jPXZ`}0lZvqr(uv>{iAzeIP5yUX5x+nd zbbwZX4O&<)z{dZBe)TMFL1*VW`qP^Jx@o`C;`NrMInC?-wW|ry>9Sp zHjFrm$RYH~G;5!Me4j8o?LJ}ooe{#?(VM`1!q03r^rXZMiaN3R9$D9LRbq!B;uL|` zY~5u%Un0!TW&V$FXtxZDzw4`e&dHYGb&VaDp6xu>_(_Q4!RH#!-O7b}E?&yP$%@ly ze9;~AJs#12C3q3ySwO2MKs(|UYwnZ+dpgAlar~S@eP&xnm~d?|?VAQ&vHTkCodyfb ztI>(3j5U(ru3hgd8WQN!+1A0`wW}e;r36hR9XX-|n9#P)hAvoPwHp5~{~T+GBT(LZ z{69U$_Zze0`;OV^o#1h|%x|zW7B}E);bB_X`@EzlYT;+in49ps#^)g(CO7S#Y3GUo2)iR7OyXE!*I_#yZKstB(OLBT;m@` z9LtySSZ4GDyee{nkmXX)1+C=f#WMVNYt7$HkP=OfK0Pb6us+ahIn2vkfBdm4b4l=D zmju=ovLNVDryHb&`)J_^Ev$DW%Jxy&xqB6ymza~1S=HUCY^ zz_p8VGACSQWF##S{OxiR?UVzxSW>l>u zTrJ5W9LUZ4cY`JDqBbd8Znb*3^Bvjj)EaW13-gli&}P^CnGEyY+U(*#m0`YHn_cEf zXV}4aYqR4!wAp1P%WCNB$Ez1*n3qs?0jMuG(PfQ~^*naHR!Tm7$hy*pX>@(5^=fhQ zJN{?V{yZ7s<TeT|2n(>?{usy?Ee1?_;dQd8>|hf$}=a`z7E%Q zb`X*e#h+_DSKRU!@tgi8o{de6=l_v281cLvx1>57^qJ4q-i||B<1R%!yB+u&hd(2pN?C3?xt%c<$=jgw=2uF!Juz?deidl z`t10&eRlewxunT?+!=f0c*HecKkeXn=h~qs(AO;21Z`NzxRjnK!#o{P7y+ z8qYg6$9uL(etk994eXZfG9EKSu3fH%?i?fzz@KY8E17HnKc)%R7sDNhV;!XDWhwYk z_}S@41+M)1;`vycW_Rj>bi2?s!BGesg1>w%1J|zVbLFoyeo2d;%cX(aia(wa9r3dM zLcEViu2}~Ges-tv#|y~c>4dKQtoZzuoT-TC)!&uh!A;5=p)27|#Ql{Zj%Qoam45-^ zSmSbyzZY@5K)J@RlJO4li`GQ55W(&`rXBaaYdn6fL)iZ!-V5=pTD$UhM?BZ~?^b>C?lnIV*t=zqJBQ0rE`UzgKeTi|0F9n8zNwyEQpkPDFq1)gs>2utmeZ zd!(Rf4e!$WeX9yvL zkmLxVyAVR?xJ?KhI)s>zBZLq_6ha6gdVKsy-WY5&<#6P!diK4#oBZIah(YfQ zaUVj7CG=4j`1b&k!>giLA?AdK>_GHw3Og9Vc47|Fl#4ltPxe=jNlYSUXFQ)A1HKsm z1IeLNgaI4}u6{0}458O8NUC#_h@8djq$wAZ(3!7PRV*O}F|8VZBe@5O|5-<%57ZL8 z%rQKHHM=2By_$-}pukH>Qw|5Bs{2S&o(6J!LaQn741Lt>2l95`$%l#CQHcc3rp5;+ z|KrH#Cvtcvf!aPuqsDik)8YTefQ`;$jngCCU$AB;Iz~Dj&erk`0$Ya2le5hl#*Sr8nfmu^9pi!u#r`4E1 zJSMNrBfSL*Aq;^J-aKl`T|kD8H02#Y*60WFks$jYKajs97(R`EkYEhRa4VvjK^Vwz zm}|->fXo6u9W*L%0Ax6vHRZ|B=Sp1LG!=(Hf&Hy1zXUS8ch{8Lfqm;A$oqmE2cf1t zKEA}Y8RS@h+L~aDuS;tTv1WqtAcrgdf8-rO{-c_~8?!_P=vKY;!T1aN3E~!N#rrpj zKPa%I|0>X2qLw#-SW|u;WOhH0;};@jKak_!a(*OViuM0d21y{tzSPWk(@*4!e&Pqa z5_b`rezHN{0OZOnzW#>;U|7mc)0j}A1%|l9G)$v;;tb3GW_Dw4zmN1onO8D9G4Ex+ zm??%#xC~)YF_ma4s=%CyGyTB*sv-XH*INBp)k6O&4V&;A3M4<9kl<}4s@pxQG{Cn2 z(fV|i=S--@DqhMidrh&APSZ)y(m`IKJy&#==p zv;{+`yJQDvgaZJ>CC*4Jbd5lUcADvJp!_)V7;Dk&iq{f`D^Re;5R)8+mQZ{G1>VAG zCMXAa^B>5oz!ciz2lCoKkt;!tm(O?pacD<^qLros7#E4QKal_V6FIyV>4$z!{KP&J z}KZHah4QvW5Q@whofu& z>DA$9Q%2Ha9hx%WMPllIC{xU-D)?R%4E$adNh0&lh6lcn1p~gP1p~gP1p~jON|MVZ z5>v=eN<37(`@@7+xk~r|2ZLsU$LtUnAq*y&G$L9PO1d%QtuBUXnW||aRhrl2H=C*7 zWR3D}TB*R6mCTmf$wG+rNr`5bx+QXxgDqETE=5N-bBt zABA5;?zS})??BNGKFioK)(*oB=8l9CdrpU~iUGgQf&~g@IX(}=fQuV0 zjLIY6HRwvE2t5P8IW5-WmRlVGw+93~0&&ej;BCa_pAG?NsxL`zfBwaVp3$ ze@PY_tYAel#|Jq+&G9vkpL6`4W36;@T!-UU9Jk}xjpLyl&*u0*I{&%kG7Fw@{Ep+V z9OrQX^)o1=MjW^1xIM>i9G9FRJ0Iq$92c^mdCY4vlw_F7fx*q_yNbS zIF@8{L7BCAPEl6nf0%IGjAI*)J8-Pe4*D?<<9HOu5gae#cqPZ{Io`?f0gg{ltd!)i zz>+iQfg=*aX&(I^gp%cOx#0B;H~VS{ZUHd_!$gD^mZp3p$Z^Z~vj;K1e9OEUoHT`x z^ebiT3;)Kj9twn)=~$MFn}rpya$`X?<>IfF-^ua%6Mq8uP66^>kRMK+nsV`1OHH}> ztEHw~{MAzPQ58NTP~wbbqDwQAnDJhL3?~jvd28+hO?e{7abnVx=F^m~203;g z$W?p8s4IMQe`&*9yvvw(o=8kvUcES_REB-4H0a5%v6A4M!Z7fg!v3ca;@OL4;VwY!a7m9-`E{*Q zONnbw9M=nn3kFmY>kLR&d*ayFg7j76#=?O+~ApBCrM}uC{{7h5I>}<=9miil7^C<)1@xrMgd0QJ?#V z75~WVfE;IRO*wuK)DYwmTo4>P7}j%!;t9nr-4kfpz15&_a7)gBrya>nh8)Y{fQi2ANE80i6F;Knr1<#YQYtVwbxWc zL4qIEAQsqI>>)ifod%8TuDiNDc1g(;G{NuI&&Wj`BspjBTf0XpUAiW zM7~o~u5N!2?$T5MW56%N<0YnIibEfbxH8fTz9xsAdmAj++!sN3VY(&t-WScV!bui(wUfa6TY8w7*cK zgAi+=nIPjQ@&iASPlJqckj8PwxaGodA3o^+J9#q@JYz-THJY!@fiYw;*Obt&0pM+! z^jHXAn~A~YEF~~f6D*V0iE)0#;L426i9yreLnD134SUV>(8U;*cdAsy(3@?cvg)0= z65qp$0pG)lfnT30*~85s761n*Vk66#wUw-TBOR;U&KD__a- z0XL~&I2tiX?-PqXov%js_^~~AgT$X1S3&hwW-JSuqX0rQJD@8VI*#>_zdHP%4#8p- z+vCO*gQk6>%H$abG1Q;>32&4Bt3Ww)q56+1-8cd6!!Y2lrLZ<>_o(J#2|mxPP+P&} zRQP=tHe$A5ec0K`bXO{_1Wkj^oIuoM5Hnt<7%X@+H|4nb^~$QHj#auTLrp2?2#%vT zj^#Lk<7AH0IL_iYm*aenA8}m5aXH8OW|WUH$L16(CDtsEbL`5o2gg1fhj1LuaU{nv z9LIB<#BnOenH=YEe3j!ubqu{)%z`qGbsJDgjW{;r*pg#=j$Jr*=h&O$K#s#Wp22Z6 z$8j7dVvM6Ig#{TLXLFp#aRJ9g9G7w|X-EZ?a%{qJQ;uaEJ9F&Du@}d_5UWRZC=1}_ zgzCW(#c?dh2^=SLoW^k$$GIHmbNq@wm17T%eK-!` zIGp21j$=5E=QxSuRE{$_&f!>HOZ9(LiH`6q?Q9b`bj-2JK=nU%9;pe4ovU5{ zBSp1#wn_Tx>?&j0`w!|8S;fe!n`f6u1N}%nqcHu*%J82sqcC&$uYRPiQKYU~Zt2-2 z%*3;c+ERxs@W1+DmXW$9p01v*k$R}^tWIm`i4H62M^-ZO>at>jfxVXQzRd;`wO|EG zH_B!nl%F?0#dBtnZh}VkKHc8b^)G~_Kjn~ZqH;G#MMkZ#y$y&xn8QPIrNmVQ5 zS57j4Lgksle^lqC1}5!|Od_@2edDyyAWJ)6Cs{kAQmJmXcB!thu6vwTymq-(l2*R9 zPpVd+wcIFCE3uMgj9#Knf<7FQSt>Q~N%yR3uufOs#VgP&S1V3S^|6M*BxQJi*x|sm zTE_E!;Sw!1N8vOK!D2b<)e8qaQ-GBa?X!3`jJJV1Wnfu#vJZhj@*)@Tz9JP~3yW;l zi1bs25U0|*qm&rIuL{wjk&Fy#!cRGoLv4xeh7pJJUw6)Rq5?$Y+5sUJ?%y$kd^z!J znB0*)IuM8UAP!_U0!IH4YKChzE`|j59Vx*JQ_3)h`K2{+A+ydFvd@NsU}~x zh-1P?KW7wi-W1~X9Vi2F;J`MxDZwuB!Mj-q$AgJ|r&Iotxq&1ooka%u-H6R2iIc4< z1N}L~0dTX44ilq^Z$2b@k62>DS9V7jW z^TZ*SkfHzep(GeOG@}w)UnK5xj}l}smqAzHRWKuu^s)O%p9+pJl>JE@a+SE76Q{pH zd=|zA7SQV^v2q^drv!oYHVFnTAp@5?#Ft@EVgmcS#A6>5Cqlt6%vDf<%L>&f83|2~ z_8t$29T$>5<{@!#CR1bF+l_i6!3jOWRoXkP#L-gIiGn7G%d1j5$T6O%OHn8 zBks_YIOzp(9Q+*|^;cgK?}8ZF=pC_@J&ZpTWU}DtY%-Yffehq)899F>t`GAA+Ly!F zz+eJ@N>ryWCmuGIYxsru&@Qr1W*!g5Xy5cJ>FpXo|EnFaK+OH(Z~`$=6n&!vdi%)U zL<_t?5OX;kTA=20@Tdj-I_oWuzWVsR2D zFZAt11@^+{e-HwUD8mTM6~dDZ#2z(?n-3%o$7aI$XM;Nl#HlpL7ZXd&DZ%^@;=IVBv?ca{`2cXW}B=4HL8MFfj3#q%04e~IW* zagf9N&*Z=!_G%dJj3fu)Ly7-@%L!}X4qGz}v*7YX4j)c@ojJviSO;1X_2w`oV{n3+ zBL@cI{0rfCNQi=b$OyxthU8GNE3bBfU&Aw8v=@g#oCzl`;q=%-s2BV)pZp0HE#w@6 z^DhL^M9v|^E8+S@2YJkQyvTvzR9KY$tA8Pyd=#Z$;6&*kjV5ls8a%fvu8pD{zDf#MvH8VYDN|p&x387QFbRF(2VB%x3n4O)lC8j%RyV zJ8;bWb8^OuMP!gNkqnX!(V&t~CN_b~2p!~4A+B7VxO5t^n<1r_L=r!S`vFADUq^3sYeNnm_Mge2FA=8%x276VKa#}FlVmUo(s%e>o;O=W+g1!Xm3B83b^Se z<_F_1j0Ni!Pytfskio;A#Ig7{9tfxEP=R8ihzG-bfHgFkPuycEariRgKx^Xsc;c@s z$e-?N;tw!2tJi;@H6)0G%S+wFe6($)t(3rZ9qD(%*Z5H{xP3d~tPSk2BiWm5B0i}i zE?}*C{f`d4wveEoDaCjJ|0hI$!(!3{zOm=BPnw-G18SV2zMPHY8t zLdZEO#FMh9$%}Uo+rb}_QD4sda1P8r*e8#6k-?4$WZ<4kJi3$$6nmWb@jTMYP7t3d zBYkobtRd;L7J zzsNO;yhPmh1L?gl6Muv8h4$hIixG8+i?5LWoU%0)AnPg#mM4%w!8PIlUD98@LA>-R zHEHNg;)m18KJXTC{}{3lDIo3)TQ@8~+#TYBR-{jTM6CR{j|_YslfVK-FD7t*LTvk- z^twgFdC)@Y%jg;L^f1zwF!!HG?DCxS+qnzHF$N<-$v?AFl4nc_gu#7wC|D8ty?$u5 z?>Q9q|5#vQKg57C@OeoE7~YQbrObYg#Br}t5B;+rcC+Z9{0$|*nGZSPE%6$j`<+XP zJ93wqzayS?jatO#1F`ogDnJ3Vwl(`NBYmhT>CHa@L;jMB@5vyeoD9bAAkOECrDrwXDuhWbKWtGW+ z{tU`cZa{2RoeRX=ZW`H(GcDvWbE*qam+Zg1CC+0`f-Y3+O-R3CC;1Dhr;YW8pQfxL zL6|8SG#X4C*p@h>3Dqc>c||lil-ZEp5SCNSK+gR1Ea}~ub+gG|j04&4Wi4xs3-E0G^|&Gd$6Y?2DNnI(*Mkv+ucEM@ld37qlk5QV6~d|31OX zHN@Vol;K&vZe`tw2dl`TWq0D^1E~wdksR~9DZMTq!6EK5#K9PRpP`f#2?O5ei!(dK zrc|8eF=ahDOzlM(ns%oGNc#}a=K_25CAQ!KhV~;qS)c4<1`*rFp+6XZ2`qTxLI&d8 z2doiZcH+DUv27OTLx=*3b0fy}r2@wAITB6zcHCtMWjGPW1p4!4Hf#(2asL^{g3leu zAcOf#8*0)b=33mOK0f4deh}G52N53!@0fx87~*Ptm6VPr4qQruGI|2>*l5`QV*>q& zBsd^ths=%Y5gUh-zJ?8P>=fb|n~75+i0?1v0!$;mpii7Now(GV*p;ukWwT-a!2-C< zC4)NsI01g~3&PB9lz~|c@yT(-x%_$s!vNxfHKgyDN^G*0_#0pM?tc-#g3T-DC)nsS z^gjw>){#NOKgggkkvLmH`ndJP{%?ro8;Cbb$UY>Ac=A=!=P z#9x$&B+%bRf?U{_V}it8#J_Ww#O)*2?MwQs{lwe55*McvyYr4HHG_BrOvUKW=K%4? z6dP{MqHAIm+ervu*L*Nub8 zUlH^2R%G9lkKb4;BaQ&Z{3VyWQ6DCw#`zM32g-nfOh z+>8pO^r8ak^LZdQyAZ?qAnN=j?fF(q927FLDmjR2NDeyGB2H$$zLwa;ob;BkKfp1Q z%6tNDxsc-;lfLC-;s^`kZPSReo8nJIA$;ROW#58$UT?}E(vnz<2Tg8EV#)91Adh)^ z2H9J-CVh_woL)wJG>X{RmiQodxv|oo1f~(>FvfxSuSLYAj>KNvq}EQv+A4CG*^W4_ z4zW>3;-|eSeJJyxh18|4ok_2MitLrHcpfl>)lEr|z-;@9xRm)C^b|I!wHw(NtfUNF zn74Y6zSy1gcCAS7+LyTY2GV=Kb;~NPPsq|5S6J z8?iX!Wi{OE;nXUAK;8@X^~mB74nG*x$nZ;Zb^4A@#Nt4dHL$@!eH7~>ZD9RJK^zOB zJjtOxpKZ|s?*CB_$9SJm7l&y?!zf3+IE3TwC-N`O%vcx+ z`!6)$Q#T~{JF&w!$}k2d8q|xQHLtov4#dx%t>C@^_2Q?GlkJGb&ql(nx53bRdognLd>>6b6ln3z@6HWrg%6ti?TGZz;zlQ4=*$sb+4&e*jx*p|>O5nYT9Nex!2ARyq;n^+L`08fT@9IPLMa-wF5vOe-{mX;I z<;>NN5zj~_{bg7i&|lzIV9Y=9HVKkY0AZIWWthRd9B$1pLD)9ZFW}44Z98#GTe44K zo;QW;WhtcJDI>l3m3W~!aW?2Nf5|6!NTlx59hBhHPGW23&9GxZeGGH@MdGlXWM4O& z9EzWnujLFLvA$zJvQOPb_L(DyAEom8-xqF$FarsmKmw%y2i%)bvIPTWiS64>>k zJ~WMZ#2{kleZ&LdZW{Ia`-um55l5#J8%!cLJHYFI8SL9J!PP@#F!oR8qr`PAh$FIz zH*_R6KS{iD5wYMPMimSbix{jHzy7pO!`nO;`eQkVf=@) zAj^yrL@|rMgu)3f>Kcgqe{r;wxc?VNPVJjZ>7_EV?=qg)-j>)D<_WBjk3De&bea18 z-`ar$HdDzUmswvzEfDBP`pvwBif5hymk~Pjb|U??T9jcPb5?uOo5@LE0IMb13m%pU z{r_LV+~?mL1SEaW&G}ZXkR2Y(CcWT2KEz21%CG_7EeEzE_KYXJWqV?qb1?s40ffNC zn+%HCpl`zWT(8~teB#^p9663S(U~$(afV(Uh|`{uUa)Khtp8X5{f=bNVH6n%9?uB` zpT76K{zeXQCZ~6AOgy6#`Rjg-2A#7D@w_zRk}kyVN_d8Yqtv%M2?jY6U+qi0xn025hw8hfU(|`p*Rrm!=J>Gon+sZr*hrh#Iv}7fqRLYaSP_E8Lt1~yu4cOBLnXV zT%!ZTVS}gu9*2oNdGYYcB6esD9OPw?jvy)(4Q;FK%5Db0(ZOW0=*;q9WzKD{hs(GEH2n$ zsUL`K`H4zy8F7r13hecX_~SV87pnY1f`>!NLF`xJwE4t&T6*dhn!Jh}$n=PvmXhAR zGV#d?RG<=l;)gJ3u|RS>N&rF{-^e60PhLU(l;tdlj3oz6`Q)fqMa1GHDMwS{8P&+4 z+>0C(8WAVKh6G!vnAsUx2n$eHgY^09iD%RzK14e#rKFez;f7>jU7HMQF~>9GPkYc| z0<$x7SRJze#P*W9#K&L|qJ1WF``P{V73G1LDh7i1qpKq&@st zO&q55DVSP79IEv87}<+Mmuwmli$j}wR;4}{hc^Y_oelHyc4nS@fY^=sd>XMAFy=2=kV*nyHaL+&9LC(83lznCb|dNInWJ54 zkfku+K0@5|FRD-uPtB>!PGcy&$2vWA{*nloNboujSw{(4)uGEMc|EanAn6M>5Z9NH zK713gKHPd?dg*539`DIMnz?=uarPF{Z|O$`NZqO=K}I7o@YzOO5=#!RGLMCFVg^3j zNgt*|dh--wX(8$JnB5#npSpweN7j*E@B?^cgZ}iDyU4(58yTcA=QZa7q>?@kHl3KD zXbii7gLO`p(ejs5d`E+zPgIYJ299@4n|%#cEbc3fLeZk_?P9$-ycM%D|kt zMkivI!=w-1N%jTI%Xw;cJ<57_>f;#Z<@3lMP6xsv-OhU0Y)ry!}hIee)E`4RIfUVLO{N#Dbs{JS!5oz8#%_qs*~ zTCkj=gSeZ-rgF~U7V*0V#Cgm^rxQorCcQj^IJAKH4$lj^cZeTeBfT$kYj=MBU&ew7 zFUY{UkP_5CNF2lb^)YeSebSrmCiZziyz&;Y+e6}l7Q`-(iFK2Sy`B({xeWb}H7>*TANro zsXLEi7KAJz195iNwmHPII+P&rK4lolN5Jfb7QyR0g84n)SY$H0elEc_W#5-WyiW!=l6N~45;;Tu>Z(Qv{0(+Rv~c`{X1_U&6d& z6Y zU9o*H;%cxK;GlN{#{4CX2U3Q)?qpyZMHz}y8V0r}7N<3+9LPS-gB@m)-p!MEVL0if z1Be4)=EMrdFmG}o`>S4+)cH$vVH!k(sDYHAcM2H@p0$rS_czkt9Z5AX8ARN(6|w6O z;@>9GRUnR)n6Z}9XZw)egP%3$`6x+n2xc}cK*n%(_&Yfa^(RhjPWmF|o{^M6aS-XN z=8%2U5MsSWRH3ZV#OG|j=j+|cU!IZ;_CF?pbPOfvd6c+-`B7)$!cfu=btjgMB_13= z8N`kwo(@|qtWZc8ac$UTBd0Pe_!*Hhiv{vLa#+fI0wx|z5D`ue^7tWD4D*sM6gMxiT37Gh&whVE@TdfBhH*k`dYL@g75#aU}+g;=rfHBPM;(WpG|yhI5{wjBJQRj zeKPZ99z%hDvi$(EZ@Pr|8V}morNk3XVR{&Uu5l#T^MM@3#B&0;n^m{K8e%Q=h5R0{xE#2xq~v(Nu#{=B=<=p}u?zB{=0v?3_%T3G)Ez zW0`elaeC$eo>|?tlKtp5q&MD1{8|Z5v(Z5^3)Xig4oM}0{U<0x*ZstI__12)A>tDq z$-d+maREHzL4RhaiQDQDOV1P6o=*N^n3XQsB*0G@XXL5%N=expN?>`35^SkK8N@Ri@z>=|E|Y$;2icon zAs)gll*k+j^8${UJsBZpSwcDa^j$0QDKn+7pNa^(p-rnE6nzUxhd_j5wEh2j2&z8t|DV>kO$z1t7ri z&5#l}8xk*q0-{56DRKQ3WN*#v7eX}(V{Xue^uE=|ex)tx6PcA=i3_XonI(m=r$ zZONdJdE^*kSuJv4nJ5%9-EVQ32fR zPyuR25hpPJjZd|7;VT<_4vqUh;v#0f-Nfb01Mw*v*c+LXzwBgWxc-{5z%7XkVwp?V z5oa(b<6|~(P{_P2n^+%5FNC*8h?_F|a{*nL52lgchq*5L!@oa8u%H`0dIip5zOtP- zpLsMsS_OR(^Sr-^^)09XFS!E7%<~dSpUONnfjEmXU09@Mxc2-S|AYx5C-C3D4@wxnMI2vwkEx3kyK{UEkWM=GFbF<)lU0ujvrtpCw05G9Uh7K12_Sq!3VX3=F=nMDE0nZ+0~clv$|crmN5 zDqR1gSs*5!6lT$fd4hR8m&nPX7$Z%YMHgi-iwYDoi$QL#__qty>wieQ?;XZ7iv)$t zqJ|~RqK1<8-={ZY7CRzqW^tLjFvC?s>%Z^60`+B<$Seww$}DP}EA+f$k~mWVCgC40 zp+()8MTW7=VxmfAwmrq`e+~=8`d!K__IxHCC<8n7rV)0*%wiBaGm9?tW)_!OII|eU z@glvF*Y`{oh|8{!S=3n4kqRI-oyN?mTw^)2dQ%B4;Ke+UH>qLFqD5kum7)g88V1?S zVkXOH7FR*BhF;Q%3Ml+pGmAkS#w^y78N^D75G1mJSX}a$MU$2?i&5_DLK%utp292& zSjc>o$4D`=Q!0%SNoPzC>+exsE{)UzcxN;3(af2jau>NUf8uSqFY{8KxI&q=c;bp? zPGSE^%$Ir7nuUz(|Exn)q5?Lk#(Tgb=DyoVU&@@hiP)$MwSe_{Vr%A7-sih9*J1yG z%u{$Vivq^{CG~jUpUeikR+Gat<`F!|@|hQ~UcW09p!yNAH(~zBHEha!m|IlFT#dUR zv@5UwN!*0RY|xHtY~o58By)`|nYFn_a%LOel)5ut&kbM>86z;NbSyu*riRZ<3Z zID-T>Xu}RtMFQTWW;4I!c_5#89^ZNuGdB=ZbvN?=81MDqvNUF1!!2m3WWf|}LU-n1 z9z{cc%%=Tg<}q9#8S_xORZ~jbSTKQ`(1-aFH(4n2S{^i!%s06P$;>|7 zC3(y*xkbvDGkA=dxKRN^)$;<3e`^+e;_KXvxhiMi!>r9MG=tfnFQY`}MF*(K)0hjn zMRJ+bxQh#zKVkuJ{V!+149>u~Cza5j6Sy#6=9$ckxyd@pFp$}i3mn0`jIWXmW(%HI z%9za#^8LR_FUoK-KSHr)?!s4r7qb&*7{Of1O`5>miwls;oXh%0%uTpLlHQbGWCpMQ z#w@7AE%3;l3@o_M%b6Q<21b2IUzG=COkZNLx)m{t#jBKAEWeU|WS_N5Nlj?Z0jD&SO@YEf^& zYy?v|vNf|dELO;_#7c=L+&-gV6dQzR5>FUN4vV0PQSbd5aTCs98nYEl-Kd|=JOZ8> zA-fGC`)g~7LzwHrM1=ZSHN*99!5OymrUWO?kU_&C#9q)vn83w{_|RG6LgvTEiKh=I z{p-!d%bBZkfi^I|gqaWhZA8ZPcN4e39yaI(s~H*`W}XMvDRQF`l)+uNOp%8%&*m1I z&YTI073!0jTfu6Fe3AJC%(Tdlfz|8(P*|-{P{syLU;}|{;!7DmhD{{06Z4>>#NNzj zVCF;pWM&I4-~#5`FbGkhI@USnh|Epo{MuP%2Xvih3??(kV3!@zMuFSKzO9Gig zxPUX5b6}!D`=!iPxqv5_V`0#vzR*ue8T8^3>iQGUhlvIaS~6GR0`_746D}jv2QW|J z0?uZB36~-2j3##G%QR~YaVC!ma z3wVfmoq9~b_|IlR84rqc%)5C^++^0`0zPIA<1tajT*_mj_E>76L>?0s%vM~$cFa$( zg82Q@ZY-F^T`-loH%}xbVdT)C$3PjgJ7@4mIO$LDpi?nBYjHExogpiIeM-KKeYd@e<-#=D)fUCong>PMpdd zuQVZt`7Cg#%LTYd4%@b-1R;gQf1Ch4{2kipK5-?u8Aaazi1-jLufQE26F_V{rgSoBHzajlx+z)_$p_<|PkH)DJ1UhfY;1AAFT1s3K2PNne-VuMq%M>``J@IS2 ztbji-*X0(P{ekqS@G=H{wKC#YT)+j$xc=4T=?!6>dk@G>;L{%FbF|l$p%uq?tx{@6Q&Z& zna|={0N)vi?@Sr&!Z8Az!5oe?2F~w7`XSilz$MJ%aZCW~cdeq%U(y?!5CrC3DZ$^k z`T@(Cop96xdoVA$LXjnbdOE(DJ4PTYahCo}tUhHgDb-Rru9Rf3z=Fp>hC3(V0_8Cu zXNP6XzT73|eaQYSj~O@SG@OVa!!TwOZb3<3vagO;jUkLb6Bd}@Oa=+Onb&fkh6&~- zj%HrPqd1ZID>rE#^C_;7i3er4jJqVVKXD%{Fuqhc-jf9I8W?o}^al{TZ~`MQVjIpN zjCna1ID`2S+ZQp9X1&WmN*~OF(wq4YXhEgAiCEB03_@ma9)yX^nIc2xk31&wn6L6> z7dePBT&)lDMpd|K<`CC;2Ve03E@Ph87Umxmc+4e(*YGq16C^W#bcTruI5CR!1;4YN zIcW?ytOgUwV$$DR4lM|5&g=(Y*{lXEXYR6}*n|1RcIbaJ2w}l}oaulgnd{-NRDk1| z=VueAGS|ieSBI}`F!zLS$W$|e%aS<=^}r>}W!l7L%>D5E5j2o2p&E>21AXSF?9hZ6 z&yqrWOXk}!5mkeqZMZNy!s3G5nYsQwum|qKJar}M-I$f1|1)EJ9&60U>-* zodSM2@W0&mfa>imgI6^@H0+!Xq`y@fT+s5L4hd$!XC{1R!3V$B9SI-&^6(t^%!Lnr zQFtDF=EG+Je4^p=2YeR7XAyj2;IkM$_=VwE_}~|Xm%(Q_eBvspj?6abrL{$+H^<=I zXeedmEfD|z%{DzF%Aiek)l*Z$#_9Xw3^r6!m7O)HswzBfpr`F9Qzc$9sH5t=*RZCR zLUrt;VXYs@YS}o21O^4m?SmA-egO(UdzoLb>V9j(=IK+`81$>As=V0HTs1!1;BLCb zb_3TMs=BugYwFq9j8G_46V4jcR&`Vvw5UIE{N!o_3!3N`9yDU=sPK>x zfkA$uK@*`8PWFLL4vzMAGADamKYx4G(mIg(Vr|1o+Nuv{4XSaY*ixgk>1k+SXfq-x z(AL4hMlr%k-8?FfriQxJ6v1|WHh~TS0X6~l0Wwv46T`st0u#fB2I-@k8XhuHncOz4 zp>6>Ce;Yux+t|=TW%}HpYE}C{M?Xh@hd@7>EHE(rNC(4M?f-Vlzxf+$$Rup+?0UuKv7b&}zgW~xem!2k_iZP=-LdeK%xnO1uE zcEh8URY%GUEVX3+w1Ry=fL)-Iy`4PJK^CY`*sEq28aSpO+H0sVR5iP3XqGY*MBQ6dhSOuY=YoGMS#M|MrNz9 zwU^nXk1sXU(o@A17&xa#d@_8mtvYoOx~%P2!`aPRjPM&beq0+{f7{?-zo1}8Kez;C z4uL^(zW|$Hxxb&kon3&Rtz8?{jwaHi=D%jF>eE!(K&5CVZ9KqEA)z#iASeGIdncKr z!r#sT#+f|G!7kW7z}`vW;0O)v)aD<{ii)DT+f+KQNkvv|Y!xaOYpJDbXEUjfYO1}| zLKWFuYGx4}1XWYmK(G(Cvy%nN{T%{=6}AdTML=MXqfI~?h3b<6k{xa?9n!PHOhoPM z>=g1zOF`l15a1uAu#?-`1j+*(6n=L0 ze!;bDrjC+!&cB6;eDiyRh_J*`sNjuxudnz)}o@;Z6jALY%8_2 z6fF_t7i{kk5ajPKgYg!ukOw&0$O2@t06C28AX|T#D%M&WWch1jxs8+RZ)<7Wic8w1 zwRA$oR##d}=QXaV)@@WZ+CUHNZzHw)g&rsbGu6_z(xi&Vwv(!HD;V3q$)rQ56Wnd2 z`W25fC-s$N>BIxA!sZRPktSE%6wbE4(qQL*$tv1T+M`K@gVn}S^`zr;>zpjy@z z2H|*n>9vZR%~5rvIV1~mklLt<9HcE(?Hr{|crL84F@`uwGb?TkMM@1V4)zLnX(W!RQWfd2GL;GJD9Cpsq`M+>AO>mYPt4umb zZGYiv>fAv(OqJ6?YE|(}X=ASnvxm`O+)=ti^}ORhL!zSTN@dVVdZgkeDC#7g_$x!g zuQLpZB`#9CiZ1|LJM{(7($?-**9^zbFo-IguWam8efmR7tm`ZtVqsIk*lA;@>fZwf zLTDG5dn(=*sO~#REv-a>D{5PC-g${ZgY<$f(oR|xw{d${X+p(TA6%twztFh0G`skA zlUAv?$!u+L@K~zuc9YI(`HM@Djjd{SbLi}G-KFDIm3l~9nmZ`$gKcbNGJpR7nO(5I zgUlwt(GKo$0v-IE9PI=BRQ-BLqbhD>TXiG%x8+e$VIvE}3MW4^H|gkK-uBFOlP(MV z#inquk@V==bwp4^Ku}oth;Tpu&>)4q&99E?em$k*EAIBYJ%8z%vQcIAgRyVdOKMxO z&t1Kw!zvyeHa2uUwdpM#(x`&#NwuXnY^hFq!fMvXU8=9rY6t&X=PtFWxZ7>i-L4Al zBORiw_!|G!!SPQoI0QNgeNFnzNa)kYVu&j+R#8G7Sf9}@~ z_mOU|xNW2RN*h#cb+YfT^njg=?jFYWlMeZXRpUs%UvX+Hqw9CNhjgCGs=w5#SH-O^ z`^9Eg_3AI(S>afz>j`7!bUzp&hdp70_}MDtc7DNfN2dTs2fskOK)5Fl^!HOZ1v)AG zY#jXB$W-go3|gx?43K75Je*`SoWi}NUP`)*E1XC~?QAO=E5fj%8K;d*{jkpb(_Lv6 zJVs9if@gN>01pY_Sn0b`c*bWEuPX79)~#|(BCT3zt}T%+zog$x z25$Gh*T(SK>aSznf7@(1I^&f2(YOI$hE$E)CXI7E)cxJJqj@dc2F@Mb*6ql}C3T$x z`d>fMIu=AM{O}!>Gs%Ue8jFQT5bF{*Z;!$67DnF4;=#v{;w$>ZRKzCMkw1~N$j@ef^7ciZ9QLZ z9Q0t;!Am2aeLHZx`(|mMw598|?&{y-k1%J;Dz@i854isNe*NL=hCW|w{^WMGH*XfX z17?bLZvxK-ukvFQ+`bGxb*HBl+E|#EtnY z@7%vvb>f)&NvU7DwA33r^m!e}%C@F!JqA{fDAc<5^t^H4(w>Ly@!kd_B;?a+h|j(Wy-bX2V!0O z+Fdj8s1!C~`rKD$GwmK8jD7m{h0UdYw;Ut{NNX~!pXb%opVyBN)}hHn(lZr zV%G;}oyAT3`gc8S{9@Lnc4O)^3t3w7_ut+2%*>5FG;nok!IRmF*6wq<)|V+dzuEur zs@;d>hR=P^uX~(UQ(N!ge1}rQ$yfI}4Xv!a>1Esf5O5`+GT8gb#A?O`zN1_D*N2nvod<gZq+Vt1 z9$7Bl>rfop-qJvSV42Eq^UX=^FGRoBD>zyA&%V}*o(D(z?|bAGCmoQ{%4gNrsQQLG zTONB_G_GUwcN0RKR@B$Gc1~1UA4qC*;k1cCi!~{3`?{{*DP5Z~P1)nc%&+>LjR*ZP zb4YB*Gt)9M$4_#*?A6)(_?kKAKTND@`rF0!_Z<@YrZrlTQEsI_?y>*ttm!X1xcM#B zb9}6AG&`L>-=pk}L#f|( z%kbVAo0`mfce|*1DE3e z?!uJe%31ef-~P69bmO>z(W}0Gllxw5b?Mx=LK}GE*rV`;i%Hrne~0$>JHLQ?%6A(&0Xc(yE|n` zv)#)UPOZDx>9$+HxsfCER{!CB;fC#Q%TNBl4f;K%XMtnrDmUe*mmh~eIMSf0@yHwA z;YYi#|MRYmb^gdcnK3W*W+rWMQWPu>xpcE~(Vl8imG`%u9MNIF>D?=3M}FJ=pm5Br z#D-O48%_GFOWfI3HD4>LRl2TR+i35Zu$ET4Kl*mbJ!se9@MMX+n$@T)@gAuw2Hn2> z@YKxp>po{)8Gg5$6E%@Y&XqpNcG`4pB9$B*KX{vLF+>K({Rtg>fZhz&NMsFOCGYd z&${Bn3#_}v`B}Uhx8}fLn@dmUrRyvx`y7$Fd}zmjk8{#p#zwb29uU_}TChmw|Lvkh zE#l{(8wavyfXo zA9$_acv|a7?1&*Xf`=^6&AYO7`j_33pYNSnC#qhrRGlM(jw0lR)@~I_jzAQa>VM7 zm)3)847pn4cBLn;7xZbi`{B_wLx+tGc&R<5Zo>8lHcr(7Y&#u#VC(v>du-*IBj!Ew zEIZrVzFX%lfqPG_-PmyW;J!U(UHa&o{chaF_hT}fPjyn-8y{@);706;#XENwZr2ODpR>N-AC|+e23g;HFt?s=?*6#;C7=A?HT1ri z6=qtg{E>;hP4gh5iia?{oK-gTo#Y^{^|V%>?luV1fg(&U|gyOCy%qb+W`n6BvC z+rE4A8XJ@TDt*|*u-l%n{tXu#%FbUla?Aq9@VD;|d~{8{w{=p_jwT_BfWGObHMD$= zEi&2nxsRWG!@Ywa8b!Nkt^K>Lqv>ZqLi z_tq0Pt1sF*q4C4GsLA0+uB|>gX7}~*XRTKsoH{M}$%7yp*LmBIIqn)Q3qN=*-E3^k z{TnAtFK^GEmH#nY@ApfCS3jTNS^3uPD-SI6CflXdHoekx=-3f+JS$DSIPy~)N$KS5 z%&UdH3Z^X5@0UGUFLKI;oVwokvYOnVylBkX53)fDWnb%L&^0xRP%YN( zbXMPE+T*&b_cXGu@w(QO4N6llw_3^5WzVcfJjm=+=+Wz$;hT_#>2F?9_lr4p#QWs z(L=6=^gWd~KmTQyeac-AI?YH}Y}G^ik1zVgbqrc)GEO&3FSCP^-y>J{m}tL@*zu9bW`=vd%4_;24v zr+YQZ$^Q^rJhNx-rgfCs=XE-a*rxk%L8FAYUebzHv6F6e};aCH7Q45y!mU0wxQ1WLt8WFwp?-Mt>nS9P0ydt8PKd?eVyo) zy`#cEdh9J5xH>3qP1R*dYjxh}>pXWieN`5E$lYN2)$vtpKOdYvZ}XA{qfS1$JlnRK zYN>VIo_m9LNuzeYy}v8T! z*dMn3-qZg2Q{Kju&!2Ol+jch>i9^`e#WVX>J1hC@mSJ-!V&3O27gUQ(92ZAbIh!=M z%fopG8f~x-Gdy<1y3wN{>z-9{EKADjJ@~_{-;V8$q)J)W-IGkUp93)HTV8sQxqrM94_DXu2YbrbMyBVXPSrBdsx_N$NACsdJbPv z+5PU)*!mqj?q7EEd3@V_?RH(iE|bga&F_8NC2v7Yb2GCUog=K$hh7+?x_FZ8$&K5V3qgPv#1w^1it zZvAnzT5hfMm2>>oj_48WHGQ+zhh?0E3CV~@%ANA8&z+^KfiGh=w5lTczSFJ&Hl5zW*?a5Gu1bll z9McIASa zamQEuzX1OT0QY+CjX} zicGZ!ZitS5kzVAV!l!-8YL10!lYS#%$}4}jYx!X>zE;qKDbYq^a!t;Z>E7sW(>c-F*Z5=bh%*m=%AEaHMJ60-4#p;^kS4wo|0#(HBO7H~e;C_!BG) z5Tn=gHDS}Xd`XCO$N94&QDf*v6Vr=atn;5({y743C%S9&&C;iG<9d-jWEXg@tWq88 zJjvSNfDWN;0?mP$jn_K#U&!saH7%{y3<2qM<90GN^`z-*q?n2x{X0Em;a-3AVDyc8 zy1oC}9$^V0mGEz?1{~ImSNGbjtf2Sr$?@P}q(A^s`pip9kn}m%D^2AMCG7eu-vA1N zc8qL0X3v$ctLqb;W}b)Uw2`j0QU#P1C5wMzehT`adOO_I2spg}*Gi?FW+#c|faZlj zKi0kdfJXR+2`q~|`NSXrywZQVlh$VVE*?_~_-dL+TwmGIJn% z5;%`8u8a?GN_yEVGT_OkD7Cfx##aKM{p3Fe=ECuefIGTz#PtZUM;0cqSkS}0wk`co zx&b>)lQR4s#=>$-6X9ftu+T>V!KRqqm9QJdAidJafuxaV4{AqD^)s4c8s&6zIvkJH z2tcz__>MVf0&?LQ^&6WWg$o3EHEYU+IX3}LqQUGe3r*Y}&PH1hO(_~^r(0{=R90mQ zy0`B|N!iO1z9~7EfM^UrfBIVjbGJ(>v2(nadf9?T--OG=2dVAVVWbWVi!NI7jpI|_ z-QH$Z>QwlkR&8t1H3j5b6zwK0M`B5pW7WnvXRi(l zcg52GTWZ{q16@HkkHEq>9p(l3nMy1?YBE{)fEu;cysJ6BM=!;WAwd8M9d)y{-Hq`r zTiRpx#u<+>_9D5*V21LHNsR{AyF8bGXbfO~*c8}%8vz!q3Ji8zta1JyveT|?tMiP8 z=t%jZFmo0~D5ph{cn|<+`PZxq%R#xwId!EcoL=qYulvt= zc!(My-tN7$vAg1sm)L6URF|!a!_$*`geU*U=V@@!8bPmw&Hp+%QN3+@XeCufCV{(u z28;gz43=%dNj|p>K1LITA<2NO!l*mLyK-H`37+IaBI6}#dF5@kB@!cSwFo^N$gDcA zwJYbeizp{=FUOD7ryf~FSX~(`bdLz`M}QZ(ha22&MABnK<@oTi46?Rv%il_z-3+oa zRL9&=O_INgM@TsWAc*dHY^^MEcv5_S4q!FhJP5sE=YuI{teRncMDqQxtG_fd-py$y z6fbHuJs%T>Y)Q2DA$z95$dX%S$@I?qz;}aTn?&x56xRhE!JsCknEbnwO`;CEjBi-z z2k?4LxG)Rcfoj*I`4`EG|IrT7^|SMT{}9EeMjkq9tuR9cTNy~LC==EJYa^9^xeJRq zzBf0t3v2R{(dfz03gP^!mYA1u;++GR2KyS{TJst7U0}e)eYhRY_Oex~gMbgL!X^4E zF|kU*DM<)4u!nwAK|R7}JxwSuW@gn71UKyfZ!?g^Lg0aeh$k!H2UWfmUP}!mHd7M? zbkQ^T5S};t=XYJ09AY`Z2W0$zk~zs7&F^W{CtW~VX@g#f#oX`ZIUDb67Y5Or6j@WUebEW(pw>$aki3GHFvOlZoG;aX=Ev?0xyrgH z2kj;ipdC~Q7^$G1d&w_F^F7sSqORRqEGQ)0wBmwOs}?mSJh{HG`~C%JQMdvWI4SXI z%JYrnw#!Oqk{l=Tnk1b7SA6d_fx=@ z5WTEd_3g6if%5|;*)8e_7%L&Ru{NuXp05G4=Qy;2iU~gBGA`R8>@I+SXsPb!Frr51Cx2{`x)+Xu_`;WR2?oIP1O@JPm(v`9{B*1+rEqURW#%^Kq&EOhJ3(UDy9=nS<46S=N%SF?w?E}%=!FD_js<5zW zX~SfFR)9qe5+mGuRNE@*#aD>E)5V9tZ$$0?s^*r6#s=UifM4hoRj;C{=tPip78^|< ciY>D|SmBGOYk(tr?#HlK?+cvZbv1KC3YI)LvH$=8 diff --git a/crypto/teddsa/teddsa_addon/src/server/index.ts b/crypto/teddsa/teddsa_addon/src/server/index.ts index 9c7c73d1a..f89b8f78b 100644 --- a/crypto/teddsa/teddsa_addon/src/server/index.ts +++ b/crypto/teddsa/teddsa_addon/src/server/index.ts @@ -11,6 +11,7 @@ import { napiSignRound2Ed25519, napiAggregateEd25519, napiVerifyEd25519, + napiExtractKeyPackageSharesEd25519, } from "../../addon/index.js"; // NOTE: NAPI-specific types (serialized bytes format) @@ -41,6 +42,11 @@ export interface NapiSignatureOutput { signature: number[]; } +export interface NapiKeyPackageShares { + signing_share: number[]; + verifying_share: number[]; +} + export function runKeygenCentralizedEd25519(): NapiCentralizedKeygenOutput { return napiKeygenCentralizedEd25519(); } @@ -96,3 +102,9 @@ export function runVerifyEd25519( Array.from(publicKeyPackage), ); } + +export function extractKeyPackageSharesEd25519( + keyPackage: Uint8Array, +): NapiKeyPackageShares { + return napiExtractKeyPackageSharesEd25519(Array.from(keyPackage)); +} diff --git a/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts b/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts index 95460b2d8..3f5fc478d 100644 --- a/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts +++ b/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts @@ -1,6 +1,10 @@ import { Participant } from "@oko-wallet/teddsa-interface"; -import { runKeygenCentralizedEd25519, runKeygenImportEd25519 } from "../server"; +import { + runKeygenCentralizedEd25519, + runKeygenImportEd25519, + extractKeyPackageSharesEd25519, +} from "../server"; export async function keygenCentralizedTest() { console.log("Testing centralized keygen...\n"); @@ -353,6 +357,129 @@ export async function keygenCentralizedConsistencyTest() { console.log("Consistency test passed"); } +export async function extractKeyPackageSharesTest() { + console.log("\nTesting extractKeyPackageSharesEd25519...\n"); + + // Generate a key_package first + const keygenOutput = runKeygenCentralizedEd25519(); + const clientKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P0].key_package, + ); + const serverKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P1].key_package, + ); + + // Extract shares from client key_package + const clientShares = extractKeyPackageSharesEd25519(clientKeyPackage); + + // Validate output structure + if (!clientShares.signing_share || clientShares.signing_share.length !== 32) { + throw new Error( + `Expected 32-byte signing_share, got ${clientShares.signing_share?.length ?? 0} bytes`, + ); + } + + if ( + !clientShares.verifying_share || + clientShares.verifying_share.length !== 32 + ) { + throw new Error( + `Expected 32-byte verifying_share, got ${clientShares.verifying_share?.length ?? 0} bytes`, + ); + } + + console.log(" ✓ Client shares extracted successfully"); + console.log(` ✓ Signing share: ${clientShares.signing_share.length} bytes`); + console.log( + ` ✓ Verifying share: ${clientShares.verifying_share.length} bytes`, + ); + + // Extract shares from server key_package + const serverShares = extractKeyPackageSharesEd25519(serverKeyPackage); + + // Validate server shares + if (!serverShares.signing_share || serverShares.signing_share.length !== 32) { + throw new Error( + `Expected 32-byte signing_share, got ${serverShares.signing_share?.length ?? 0} bytes`, + ); + } + + if ( + !serverShares.verifying_share || + serverShares.verifying_share.length !== 32 + ) { + throw new Error( + `Expected 32-byte verifying_share, got ${serverShares.verifying_share?.length ?? 0} bytes`, + ); + } + + console.log(" ✓ Server shares extracted successfully"); + + // Verify that client and server shares are different + const clientSigningShareHex = Buffer.from( + clientShares.signing_share, + ).toString("hex"); + const serverSigningShareHex = Buffer.from( + serverShares.signing_share, + ).toString("hex"); + if (clientSigningShareHex === serverSigningShareHex) { + throw new Error("Client and server signing shares should be different"); + } + + const clientVerifyingShareHex = Buffer.from( + clientShares.verifying_share, + ).toString("hex"); + const serverVerifyingShareHex = Buffer.from( + serverShares.verifying_share, + ).toString("hex"); + if (clientVerifyingShareHex === serverVerifyingShareHex) { + throw new Error("Client and server verifying shares should be different"); + } + + console.log(" ✓ Client and server shares are different"); + + // Test with invalid key_package + try { + const invalidKeyPackage = new Uint8Array(32).fill(0xff); + extractKeyPackageSharesEd25519(invalidKeyPackage); + throw new Error("Should have thrown an error for invalid key_package"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") + ) { + throw new Error( + `Unexpected error for invalid key_package: ${error.message}`, + ); + } + console.log(" ✓ Invalid key_package correctly rejected"); + } + + // Test consistency: extract from same key_package multiple times + const shares1 = extractKeyPackageSharesEd25519(clientKeyPackage); + const shares2 = extractKeyPackageSharesEd25519(clientKeyPackage); + + const signingShare1Hex = Buffer.from(shares1.signing_share).toString("hex"); + const signingShare2Hex = Buffer.from(shares2.signing_share).toString("hex"); + if (signingShare1Hex !== signingShare2Hex) { + throw new Error("Extraction should be deterministic"); + } + + const verifyingShare1Hex = Buffer.from(shares1.verifying_share).toString( + "hex", + ); + const verifyingShare2Hex = Buffer.from(shares2.verifying_share).toString( + "hex", + ); + if (verifyingShare1Hex !== verifyingShare2Hex) { + throw new Error("Extraction should be deterministic"); + } + + console.log(" ✓ Extraction is deterministic"); + + console.log("\nExtract key package shares test passed"); +} + // Run the tests async function main() { console.log("Starting Ed25519 keygen tests...\n"); @@ -366,6 +493,7 @@ async function main() { await keygenImportErrorTest(); await keygenImportEdgeCasesTest(); await keygenCentralizedConsistencyTest(); + await extractKeyPackageSharesTest(); console.log("\n" + "=".repeat(50)); console.log("All keygen tests passed!"); From 598bfb4f32e04e2aace21103780f94560b2dd3d1 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Thu, 8 Jan 2026 19:00:21 +0900 Subject: [PATCH 02/17] tss_api: refactor Ed25519 keygen to store only signing/verifying shares --- .../tss_api/src/api/keygen_ed25519/index.ts | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/backend/tss_api/src/api/keygen_ed25519/index.ts b/backend/tss_api/src/api/keygen_ed25519/index.ts index dabfdd221..30eca01d3 100644 --- a/backend/tss_api/src/api/keygen_ed25519/index.ts +++ b/backend/tss_api/src/api/keygen_ed25519/index.ts @@ -21,6 +21,7 @@ import { import { getKeyShareNodeMeta } from "@oko-wallet/oko-pg-interface/key_share_node_meta"; import { generateUserToken } from "@oko-wallet-tss-api/api/keplr_auth"; +import { extractKeyPackageSharesEd25519 } from "@oko-wallet/teddsa-addon/src/server"; export async function runKeygenEd25519( db: Pool, @@ -114,10 +115,7 @@ export async function runKeygenEd25519( }; } - // Ed25519 uses 2-of-2 threshold signature with server, not SSS key share - // nodes - // Skip checkKeyShareFromKSNodes validation (which expects secp256k1 - // 33-byte keys) + // TODO: Add KS node check after SSS & KSN logic is implemented const getActiveKSNodesRes = await getActiveKSNodes(db); if (getActiveKSNodesRes.success === false) { return { @@ -129,14 +127,19 @@ export async function runKeygenEd25519( const activeKSNodes = getActiveKSNodesRes.data; const ksNodeIds: string[] = activeKSNodes.map((node) => node.node_id); - const keyPackageJson = JSON.stringify({ - key_package: keygen_2.key_package, - public_key_package: keygen_2.public_key_package, - identifier: keygen_2.identifier, - }); + // Extract signing_share and verifying_share from key_package + const keyPackageShares = extractKeyPackageSharesEd25519( + new Uint8Array(keygen_2.key_package), + ); + + // Store only signing_share and verifying_share (64 bytes total) + const sharesData = { + signing_share: keyPackageShares.signing_share, + verifying_share: keyPackageShares.verifying_share, + }; const encryptedShare = await encryptDataAsync( - keyPackageJson, + JSON.stringify(sharesData), encryptionSecret, ); const encryptedShareBuffer = Buffer.from(encryptedShare, "utf-8"); From d6b617d9c7322424fac8804ee47a7e9f0545bd9b Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Thu, 8 Jan 2026 19:28:12 +0900 Subject: [PATCH 03/17] tss_api: refactor keygen test --- .../src/api/keygen_ed25519/index.test.ts | 78 +++++++++++++++++- .../addon/teddsa-addon.darwin-arm64.node | Bin 814624 -> 814624 bytes 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/backend/tss_api/src/api/keygen_ed25519/index.test.ts b/backend/tss_api/src/api/keygen_ed25519/index.test.ts index c748e8d24..a48a402eb 100644 --- a/backend/tss_api/src/api/keygen_ed25519/index.test.ts +++ b/backend/tss_api/src/api/keygen_ed25519/index.test.ts @@ -5,9 +5,14 @@ import { runKeygenCentralizedEd25519 } from "@oko-wallet/teddsa-addon/src/server import { createPgConn } from "@oko-wallet/postgres-lib"; import { insertKSNode } from "@oko-wallet/oko-pg-interface/ks_nodes"; import { createUser } from "@oko-wallet/oko-pg-interface/oko_users"; -import { createWallet } from "@oko-wallet/oko-pg-interface/oko_wallets"; +import { + createWallet, + getWalletById, +} from "@oko-wallet/oko-pg-interface/oko_wallets"; import { insertKeyShareNodeMeta } from "@oko-wallet/oko-pg-interface/key_share_node_meta"; import type { WalletStatus } from "@oko-wallet/oko-types/wallets"; +import { decryptDataAsync } from "@oko-wallet/crypto-js/node"; +import { extractKeyPackageSharesEd25519 } from "@oko-wallet/teddsa-addon/src/server"; import { resetPgDatabase } from "@oko-wallet-tss-api/testing/database"; import { testPgConfig } from "@oko-wallet-tss-api/database/test_config"; @@ -106,6 +111,12 @@ describe("Ed25519 Keygen", () => { TEMP_ENC_SECRET, ); + if (!result.success) { + console.error("Keygen failed:", { + code: result.code, + msg: result.msg, + }); + } expect(result.success).toBe(true); if (result.success) { expect(result.data.token).toBeDefined(); @@ -342,5 +353,70 @@ describe("Ed25519 Keygen", () => { // In production, the user_id would come from the database } }); + + it("should store only signing_share and verifying_share in enc_tss_share", async () => { + await setUpKSNodes(pool); + await setUpKeyShareNodeMeta(pool); + + const keygenResult = runKeygenCentralizedEd25519(); + const serverKeygenOutput = keygenResult.keygen_outputs[Participant.P1]; + + // Extract expected shares from server key_package + const expectedShares = extractKeyPackageSharesEd25519( + new Uint8Array(serverKeygenOutput.key_package), + ); + + const request = generateKeygenRequest(keygenResult); + + const result = await runKeygenEd25519( + pool, + TEST_JWT_CONFIG, + request, + TEMP_ENC_SECRET, + ); + + expect(result.success).toBe(true); + if (result.success) { + // Get wallet from database using wallet_id from result + const getWalletRes = await getWalletById( + pool, + result.data.user.wallet_id, + ); + expect(getWalletRes.success).toBe(true); + if (getWalletRes.success && getWalletRes.data) { + const wallet = getWalletRes.data; + + // Decrypt enc_tss_share + const encryptedShare = wallet.enc_tss_share.toString("utf-8"); + const decryptedShare = await decryptDataAsync( + encryptedShare, + TEMP_ENC_SECRET, + ); + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; + }; + + // Verify structure: should only have signing_share and verifying_share + expect(storedShares).toHaveProperty("signing_share"); + expect(storedShares).toHaveProperty("verifying_share"); + expect(storedShares).not.toHaveProperty("key_package"); + expect(storedShares).not.toHaveProperty("public_key_package"); + expect(storedShares).not.toHaveProperty("identifier"); + + // Verify sizes: each should be 32 bytes + expect(storedShares.signing_share).toHaveLength(32); + expect(storedShares.verifying_share).toHaveLength(32); + + // Verify values match expected shares + expect(storedShares.signing_share).toEqual( + expectedShares.signing_share, + ); + expect(storedShares.verifying_share).toEqual( + expectedShares.verifying_share, + ); + } + } + }); }); }); diff --git a/crypto/teddsa/teddsa_addon/addon/teddsa-addon.darwin-arm64.node b/crypto/teddsa/teddsa_addon/addon/teddsa-addon.darwin-arm64.node index e71fa80315c0d6677134fc41073c84c22a98c3ea..92ada7bbcf6a379ac65c9d3f3ddfa3c200e3bdbf 100755 GIT binary patch delta 171 zcmZ2*$8fel8T?Cn3;8G)Dyh?#+y1&CRJm<@QT1r-i*%$*&QvABsR$o}evn0@!u zD!(!%#m+p=^7(4#)KhOHwl{?GBnT>Z;n`6|YzS O%+9>~_qGfk1vUVMd`ofw delta 171 zcmZ2*$8f Date: Thu, 8 Jan 2026 20:05:56 +0900 Subject: [PATCH 04/17] tss_api: refactor presign_ed25519 --- .../tss_api/src/api/presign_ed25519/index.ts | 41 ++++++++++++++++--- .../teddsa/teddsa_addon/src/server/index.ts | 19 +++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/backend/tss_api/src/api/presign_ed25519/index.ts b/backend/tss_api/src/api/presign_ed25519/index.ts index 71c649019..cc656a93d 100644 --- a/backend/tss_api/src/api/presign_ed25519/index.ts +++ b/backend/tss_api/src/api/presign_ed25519/index.ts @@ -11,11 +11,17 @@ import { TssStageType, PresignEd25519StageStatus, } from "@oko-wallet/oko-types/tss"; -import type { KeygenEd25519Output } from "@oko-wallet/oko-types/tss"; import type { OkoApiResponse } from "@oko-wallet/oko-types/api_response"; import { Pool } from "pg"; import { decryptDataAsync } from "@oko-wallet/crypto-js/node"; -import { runSignRound1Ed25519 } from "@oko-wallet/teddsa-addon/src/server"; +import { + runSignRound1Ed25519, + reconstructKeyPackageEd25519, +} from "@oko-wallet/teddsa-addon/src/server"; +import { + Participant, + participantToIdentifier, +} from "@oko-wallet/teddsa-interface"; import { validateWalletEmail } from "@oko-wallet-tss-api/api/utils"; @@ -54,12 +60,35 @@ export async function runPresignEd25519( encryptedShare, encryptionSecret, ); - const keygenOutput: KeygenEd25519Output = JSON.parse(decryptedShare); + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; + }; + + // Reconstruct key_package from stored shares + const serverIdentifier = participantToIdentifier(Participant.P1); + const verifyingKey = Array.from(wallet.public_key); + const minSigners = 2; + + let keyPackageBytes: Uint8Array; + try { + keyPackageBytes = reconstructKeyPackageEd25519( + new Uint8Array(storedShares.signing_share), + new Uint8Array(storedShares.verifying_share), + new Uint8Array(serverIdentifier), + new Uint8Array(verifyingKey), + minSigners, + ); + } catch (error) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to reconstruct key_package: ${error instanceof Error ? error.message : String(error)}`, + }; + } // Generate nonces and commitments (Round 1 without message) - const round1Result = runSignRound1Ed25519( - new Uint8Array(keygenOutput.key_package), - ); + const round1Result = runSignRound1Ed25519(keyPackageBytes); // Create TSS session const sessionRes = await createTssSession(db, { diff --git a/crypto/teddsa/teddsa_addon/src/server/index.ts b/crypto/teddsa/teddsa_addon/src/server/index.ts index f89b8f78b..97e446ebb 100644 --- a/crypto/teddsa/teddsa_addon/src/server/index.ts +++ b/crypto/teddsa/teddsa_addon/src/server/index.ts @@ -12,6 +12,7 @@ import { napiAggregateEd25519, napiVerifyEd25519, napiExtractKeyPackageSharesEd25519, + napiReconstructKeyPackageEd25519, } from "../../addon/index.js"; // NOTE: NAPI-specific types (serialized bytes format) @@ -108,3 +109,21 @@ export function extractKeyPackageSharesEd25519( ): NapiKeyPackageShares { return napiExtractKeyPackageSharesEd25519(Array.from(keyPackage)); } + +export function reconstructKeyPackageEd25519( + signingShare: Uint8Array, + verifyingShare: Uint8Array, + identifier: Uint8Array, + verifyingKey: Uint8Array, + minSigners: number, +): Uint8Array { + return new Uint8Array( + napiReconstructKeyPackageEd25519( + Array.from(signingShare), + Array.from(verifyingShare), + Array.from(identifier), + Array.from(verifyingKey), + minSigners, + ), + ); +} From d9d5e942c9be71013109e93a2e716bc65d0d07c3 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 11:32:49 +0900 Subject: [PATCH 05/17] tss_api: add Ed25519 presign test --- .../src/api/presign_ed25519/index.test.ts | 368 ++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 backend/tss_api/src/api/presign_ed25519/index.test.ts diff --git a/backend/tss_api/src/api/presign_ed25519/index.test.ts b/backend/tss_api/src/api/presign_ed25519/index.test.ts new file mode 100644 index 000000000..cbc01da0a --- /dev/null +++ b/backend/tss_api/src/api/presign_ed25519/index.test.ts @@ -0,0 +1,368 @@ +import { Pool } from "pg"; +import type { PresignEd25519Request } from "@oko-wallet/oko-types/tss"; +import { Participant } from "@oko-wallet/teddsa-interface"; +import { runKeygenCentralizedEd25519 } from "@oko-wallet/teddsa-addon/src/server"; +import { createPgConn } from "@oko-wallet/postgres-lib"; +import { insertKSNode } from "@oko-wallet/oko-pg-interface/ks_nodes"; +import { createUser } from "@oko-wallet/oko-pg-interface/oko_users"; +import { + createWallet, + getWalletById, +} from "@oko-wallet/oko-pg-interface/oko_wallets"; +import { insertKeyShareNodeMeta } from "@oko-wallet/oko-pg-interface/key_share_node_meta"; +import { insertCustomer } from "@oko-wallet/oko-pg-interface/customers"; +import type { WalletStatus } from "@oko-wallet/oko-types/wallets"; +import { + TssStageType, + PresignEd25519StageStatus, +} from "@oko-wallet/oko-types/tss"; +import { getTssStageWithSessionData } from "@oko-wallet/oko-pg-interface/tss"; + +import { resetPgDatabase } from "@oko-wallet-tss-api/testing/database"; +import { testPgConfig } from "@oko-wallet-tss-api/database/test_config"; +import { runKeygenEd25519 } from "@oko-wallet-tss-api/api/keygen_ed25519"; +import { runPresignEd25519 } from "@oko-wallet-tss-api/api/presign_ed25519"; +import { TEMP_ENC_SECRET } from "@oko-wallet-tss-api/api/utils"; +import { TEST_CUSTOMER } from "@oko-wallet-tss-api/api/tests"; + +const SSS_THRESHOLD = 2; +const TEST_EMAIL = "presign-ed25519-test@test.com"; +const TEST_JWT_CONFIG = { + secret: "test-jwt-secret-for-presign-ed25519", + expires_in: "1h", +}; + +async function setUpKSNodes(pool: Pool): Promise { + const ksNodeNames = ["ksNode1", "ksNode2"]; + const ksNodeIds = []; + const createKSNodesRes = await Promise.all( + ksNodeNames.map((ksNodeName) => + insertKSNode(pool, ksNodeName, `http://test.com/${ksNodeName}`), + ), + ); + for (const res of createKSNodesRes) { + if (res.success === false) { + throw new Error("Failed to create ks nodes"); + } + ksNodeIds.push(res.data.node_id); + } + return ksNodeIds; +} + +async function setUpKeyShareNodeMeta(pool: Pool): Promise { + await insertKeyShareNodeMeta(pool, { + sss_threshold: SSS_THRESHOLD, + }); +} + +async function setUpEd25519Wallet( + pool: Pool, + email: string = TEST_EMAIL, +): Promise<{ walletId: string; customerId: string }> { + // Create customer + const insertCustomerRes = await insertCustomer(pool, TEST_CUSTOMER); + if (insertCustomerRes.success === false) { + throw new Error(`Failed to create customer: ${insertCustomerRes.err}`); + } + + // Set up KS nodes and metadata + await setUpKSNodes(pool); + await setUpKeyShareNodeMeta(pool); + + // Create wallet using keygen + const keygenResult = runKeygenCentralizedEd25519(); + const serverKeygenOutput = keygenResult.keygen_outputs[Participant.P1]; + + const keygenRequest = { + auth_type: "google" as const, + user_identifier: email, + keygen_2: { + ...serverKeygenOutput, + public_key: [...keygenResult.public_key], + }, + email: email, + }; + + const keygenResult_res = await runKeygenEd25519( + pool, + TEST_JWT_CONFIG, + keygenRequest, + TEMP_ENC_SECRET, + ); + + if (!keygenResult_res.success) { + throw new Error(`Failed to create wallet: ${keygenResult_res.msg}`); + } + + return { + walletId: keygenResult_res.data.user.wallet_id, + customerId: TEST_CUSTOMER.customer_id, + }; +} + +function generatePresignRequest( + email: string, + walletId: string, + customerId: string, +): PresignEd25519Request { + return { + email, + wallet_id: walletId, + customer_id: customerId, + }; +} + +describe("Ed25519 Presign", () => { + let pool: Pool; + + beforeAll(async () => { + const config = testPgConfig; + const createPostgresRes = await createPgConn({ + database: config.database, + host: config.host, + password: config.password, + user: config.user, + port: config.port, + ssl: config.ssl, + }); + + if (createPostgresRes.success === false) { + console.error(createPostgresRes.err); + throw new Error("Failed to create postgres database"); + } + + pool = createPostgresRes.data; + }); + + afterAll(async () => { + await pool.end(); + }); + + beforeEach(async () => { + await resetPgDatabase(pool); + }); + + describe("runPresignEd25519", () => { + it("should successfully generate presign and create session", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + + const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); + + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + if (!result.success) { + console.error("Presign failed:", { + code: result.code, + msg: result.msg, + }); + } + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.session_id).toBeDefined(); + expect(result.data.commitments_0).toBeDefined(); + expect(result.data.commitments_0.identifier).toBeDefined(); + expect(result.data.commitments_0.commitments).toBeDefined(); + expect(result.data.commitments_0.identifier.length).toBe(32); + expect(result.data.commitments_0.commitments.length).toBeGreaterThan(0); + } + }); + + it("should create TSS session and stage in database", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + + const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); + + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(true); + if (result.success) { + const sessionId = result.data.session_id; + + // Verify TSS session was created + const sessionQuery = await pool.query( + "SELECT session_id, wallet_id, customer_id FROM tss_sessions WHERE session_id = $1", + [sessionId], + ); + expect(sessionQuery.rows).toHaveLength(1); + expect(sessionQuery.rows[0].wallet_id).toBe(walletId); + expect(sessionQuery.rows[0].customer_id).toBe(customerId); + + // Verify TSS stage was created + const getStageRes = await getTssStageWithSessionData( + pool, + sessionId, + TssStageType.PRESIGN_ED25519, + ); + expect(getStageRes.success).toBe(true); + if (getStageRes.success && getStageRes.data) { + const stage = getStageRes.data; + expect(stage.session_id).toBe(sessionId); + expect(stage.stage_type).toBe(TssStageType.PRESIGN_ED25519); + expect(stage.stage_status).toBe(PresignEd25519StageStatus.COMPLETED); + expect(stage.stage_data).toBeDefined(); + + const stageData = stage.stage_data as { + nonces: number[]; + identifier: number[]; + commitments: number[]; + }; + expect(stageData.nonces).toBeDefined(); + expect(stageData.identifier).toBeDefined(); + expect(stageData.commitments).toBeDefined(); + expect(stageData.identifier.length).toBe(32); + } + } + }); + + it("should return valid commitments structure", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + + const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); + + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(true); + if (result.success) { + const commitments = result.data.commitments_0; + + // Verify commitments structure + expect(commitments).toBeDefined(); + expect(commitments.identifier).toBeDefined(); + expect(Array.isArray(commitments.identifier)).toBe(true); + expect(commitments.identifier.length).toBe(32); + + expect(commitments.commitments).toBeDefined(); + expect(Array.isArray(commitments.commitments)).toBe(true); + expect(commitments.commitments.length).toBeGreaterThan(0); + } + }); + + it("should fail with UNAUTHORIZED for invalid email", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + + const request = generatePresignRequest( + "wrong-email@test.com", + walletId, + customerId, + ); + + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("UNAUTHORIZED"); + } + }); + + it("should fail with UNAUTHORIZED for invalid wallet_id", async () => { + const { customerId } = await setUpEd25519Wallet(pool); + + const request = generatePresignRequest( + TEST_EMAIL, + "invalid-wallet-id", + customerId, + ); + + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("UNAUTHORIZED"); + } + }); + + it("should fail with INVALID_WALLET_TYPE for non-ed25519 wallet", async () => { + // Create user and secp256k1 wallet + const createUserRes = await createUser(pool, TEST_EMAIL, "google"); + expect(createUserRes.success).toBe(true); + if (!createUserRes.success) { + throw new Error("Failed to create user"); + } + + const userId = createUserRes.data.user_id; + + // Create secp256k1 wallet + const createWalletRes = await createWallet(pool, { + user_id: userId, + curve_type: "secp256k1", + public_key: Buffer.from("03" + "00".repeat(32), "hex"), + enc_tss_share: Buffer.from("encrypted-share", "utf-8"), + sss_threshold: SSS_THRESHOLD, + status: "ACTIVE" as WalletStatus, + }); + expect(createWalletRes.success).toBe(true); + if (!createWalletRes.success) { + throw new Error("Failed to create wallet"); + } + + const walletId = createWalletRes.data.wallet_id; + const insertCustomerRes = await insertCustomer(pool, TEST_CUSTOMER); + if (insertCustomerRes.success === false) { + throw new Error("Failed to create customer"); + } + + const request = generatePresignRequest( + TEST_EMAIL, + walletId, + TEST_CUSTOMER.customer_id, + ); + + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("INVALID_WALLET_TYPE"); + expect(result.msg).toContain("not ed25519 type"); + } + }); + + it("should handle multiple presigns for same wallet", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + + // Generate first presign + const request1 = generatePresignRequest(TEST_EMAIL, walletId, customerId); + const result1 = await runPresignEd25519(pool, TEMP_ENC_SECRET, request1); + + expect(result1.success).toBe(true); + + // Generate second presign + const request2 = generatePresignRequest(TEST_EMAIL, walletId, customerId); + const result2 = await runPresignEd25519(pool, TEMP_ENC_SECRET, request2); + + expect(result2.success).toBe(true); + if (result1.success && result2.success) { + // Should create different sessions + expect(result1.data.session_id).not.toBe(result2.data.session_id); + + // Both should have valid commitments + expect(result1.data.commitments_0).toBeDefined(); + expect(result2.data.commitments_0).toBeDefined(); + } + }); + + it("should reconstruct key_package from stored shares correctly", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + + // Get wallet to verify shares are stored correctly + const getWalletRes = await getWalletById(pool, walletId); + expect(getWalletRes.success).toBe(true); + if (!getWalletRes.success || !getWalletRes.data) { + throw new Error("Failed to get wallet"); + } + + const wallet = getWalletRes.data; + expect(wallet.curve_type).toBe("ed25519"); + + // Presign should succeed using reconstructed key_package + const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); + const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(true); + if (result.success) { + // If key_package reconstruction failed, we would get an error + // So success means reconstruction worked + expect(result.data.session_id).toBeDefined(); + } + }); + }); +}); From 181083ce03de40004a13626d8b1a0104355fc8ba Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 12:56:53 +0900 Subject: [PATCH 06/17] tss_api: refactor sign_ed25519 --- backend/tss_api/src/api/sign_ed25519/index.ts | 117 ++++++++++++++---- 1 file changed, 90 insertions(+), 27 deletions(-) diff --git a/backend/tss_api/src/api/sign_ed25519/index.ts b/backend/tss_api/src/api/sign_ed25519/index.ts index 38c9eed68..baff1e428 100644 --- a/backend/tss_api/src/api/sign_ed25519/index.ts +++ b/backend/tss_api/src/api/sign_ed25519/index.ts @@ -21,7 +21,6 @@ import { PresignEd25519StageStatus, TssSessionState, } from "@oko-wallet/oko-types/tss"; -import type { KeygenEd25519Output } from "@oko-wallet/oko-types/tss"; import type { OkoApiResponse } from "@oko-wallet/oko-types/api_response"; import { Pool } from "pg"; import { decryptDataAsync } from "@oko-wallet/crypto-js/node"; @@ -29,7 +28,12 @@ import { runSignRound1Ed25519, runSignRound2Ed25519, runAggregateEd25519, + reconstructKeyPackageEd25519, } from "@oko-wallet/teddsa-addon/src/server"; +import { + Participant, + participantToIdentifier, +} from "@oko-wallet/teddsa-interface"; import { validateWalletEmail, @@ -73,11 +77,34 @@ export async function runSignEd25519Round1( encryptedShare, encryptionSecret, ); - const keygenOutput: KeygenEd25519Output = JSON.parse(decryptedShare); + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; + }; - const round1Result = runSignRound1Ed25519( - new Uint8Array(keygenOutput.key_package), - ); + // Reconstruct key_package from stored shares + const serverIdentifier = participantToIdentifier(Participant.P1); + const verifyingKey = Array.from(wallet.public_key); + const minSigners = 2; + + let keyPackageBytes: Uint8Array; + try { + keyPackageBytes = reconstructKeyPackageEd25519( + new Uint8Array(storedShares.signing_share), + new Uint8Array(storedShares.verifying_share), + new Uint8Array(serverIdentifier), + new Uint8Array(verifyingKey), + minSigners, + ); + } catch (error) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to reconstruct key_package: ${error instanceof Error ? error.message : String(error)}`, + }; + } + + const round1Result = runSignRound1Ed25519(keyPackageBytes); // Create TSS session const sessionRes = await createTssSession(db, { @@ -219,7 +246,32 @@ export async function runSignEd25519Round2( encryptedShare, encryptionSecret, ); - const keygenOutput: KeygenEd25519Output = JSON.parse(decryptedShare); + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; + }; + + // Reconstruct key_package from stored shares + const serverIdentifier = participantToIdentifier(Participant.P1); + const verifyingKey = Array.from(wallet.public_key); + const minSigners = 2; + + let keyPackageBytes: Uint8Array; + try { + keyPackageBytes = reconstructKeyPackageEd25519( + new Uint8Array(storedShares.signing_share), + new Uint8Array(storedShares.verifying_share), + new Uint8Array(serverIdentifier), + new Uint8Array(verifyingKey), + minSigners, + ); + } catch (error) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to reconstruct key_package: ${error instanceof Error ? error.message : String(error)}`, + }; + } const serverCommitment = { identifier, @@ -235,7 +287,7 @@ export async function runSignEd25519Round2( const round2Result = runSignRound2Ed25519( new Uint8Array(msg), - new Uint8Array(keygenOutput.key_package), + keyPackageBytes, new Uint8Array(nonces), allCommitments, ); @@ -360,7 +412,32 @@ export async function runSignEd25519( encryptedShare, encryptionSecret, ); - const keygenOutput: KeygenEd25519Output = JSON.parse(decryptedShare); + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; + }; + + // Reconstruct key_package from stored shares + const serverIdentifier = participantToIdentifier(Participant.P1); + const verifyingKey = Array.from(wallet.public_key); + const minSigners = 2; + + let keyPackageBytes: Uint8Array; + try { + keyPackageBytes = reconstructKeyPackageEd25519( + new Uint8Array(storedShares.signing_share), + new Uint8Array(storedShares.verifying_share), + new Uint8Array(serverIdentifier), + new Uint8Array(verifyingKey), + minSigners, + ); + } catch (error) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to reconstruct key_package: ${error instanceof Error ? error.message : String(error)}`, + }; + } const serverCommitment = { identifier, @@ -376,7 +453,7 @@ export async function runSignEd25519( const round2Result = runSignRound2Ed25519( new Uint8Array(msg), - new Uint8Array(keygenOutput.key_package), + keyPackageBytes, new Uint8Array(nonces), allCommitments, ); @@ -449,25 +526,11 @@ export async function runSignEd25519Aggregate( }; } - const encryptedShare = wallet.enc_tss_share.toString("utf-8"); - const decryptedShare = await decryptDataAsync( - encryptedShare, - encryptionSecret, - ); - const keygenOutput: KeygenEd25519Output = JSON.parse(decryptedShare); - - const aggregateResult = runAggregateEd25519( - new Uint8Array(msg), - all_commitments, - all_signature_shares, - new Uint8Array(keygenOutput.public_key_package), - ); - + // @TODO: Implement public_key_package reconstruction return { - success: true, - data: { - signature: aggregateResult.signature, - }, + success: false, + code: "UNKNOWN_ERROR", + msg: "public_key_package reconstruction not yet implemented. Please store public_key_package separately in wallet or require it in the request.", }; } catch (error) { return { From ceb18eb27950bd61753dcee3d5c5d83f2b130cb2 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 14:27:02 +0900 Subject: [PATCH 07/17] teddsa_addon: add reconstruct_public_key_package --- crypto/teddsa/teddsa_addon/addon/index.d.ts | 2 + crypto/teddsa/teddsa_addon/addon/index.js | 3 +- .../teddsa/teddsa_addon/addon/src/keygen.rs | 67 ++++++++++++++++++ .../addon/teddsa-addon.darwin-arm64.node | Bin 814624 -> 832000 bytes .../teddsa/teddsa_addon/src/server/index.ts | 19 +++++ 5 files changed, 90 insertions(+), 1 deletion(-) diff --git a/crypto/teddsa/teddsa_addon/addon/index.d.ts b/crypto/teddsa/teddsa_addon/addon/index.d.ts index 8e5d32804..5f78ce633 100644 --- a/crypto/teddsa/teddsa_addon/addon/index.d.ts +++ b/crypto/teddsa/teddsa_addon/addon/index.d.ts @@ -28,6 +28,8 @@ export interface NapiKeyPackageShares { export declare function napiExtractKeyPackageSharesEd25519(keyPackageBytes: Array): NapiKeyPackageShares /** Reconstruct a key_package from signing_share, verifying_share, identifier, and verifying_key. */ export declare function napiReconstructKeyPackageEd25519(signingShare: Array, verifyingShare: Array, identifier: Array, verifyingKey: Array, minSigners: number): Array +/** Reconstruct a public_key_package from verifying_shares, identifiers, and verifying_key. */ +export declare function napiReconstructPublicKeyPackageEd25519(clientVerifyingShare: Array, clientIdentifier: Array, serverVerifyingShare: Array, serverIdentifier: Array, verifyingKey: Array): Array /** Output from a signing round 1 (commitment) */ export interface NapiSigningCommitmentOutput { nonces: Array diff --git a/crypto/teddsa/teddsa_addon/addon/index.js b/crypto/teddsa/teddsa_addon/addon/index.js index fea56d1ea..779f42f18 100644 --- a/crypto/teddsa/teddsa_addon/addon/index.js +++ b/crypto/teddsa/teddsa_addon/addon/index.js @@ -310,12 +310,13 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { napiKeygenCentralizedEd25519, napiKeygenImportEd25519, napiExtractKeyPackageSharesEd25519, napiReconstructKeyPackageEd25519, napiSignRound1Ed25519, napiSignRound2Ed25519, napiAggregateEd25519, napiVerifyEd25519 } = nativeBinding +const { napiKeygenCentralizedEd25519, napiKeygenImportEd25519, napiExtractKeyPackageSharesEd25519, napiReconstructKeyPackageEd25519, napiReconstructPublicKeyPackageEd25519, napiSignRound1Ed25519, napiSignRound2Ed25519, napiAggregateEd25519, napiVerifyEd25519 } = nativeBinding module.exports.napiKeygenCentralizedEd25519 = napiKeygenCentralizedEd25519 module.exports.napiKeygenImportEd25519 = napiKeygenImportEd25519 module.exports.napiExtractKeyPackageSharesEd25519 = napiExtractKeyPackageSharesEd25519 module.exports.napiReconstructKeyPackageEd25519 = napiReconstructKeyPackageEd25519 +module.exports.napiReconstructPublicKeyPackageEd25519 = napiReconstructPublicKeyPackageEd25519 module.exports.napiSignRound1Ed25519 = napiSignRound1Ed25519 module.exports.napiSignRound2Ed25519 = napiSignRound2Ed25519 module.exports.napiAggregateEd25519 = napiAggregateEd25519 diff --git a/crypto/teddsa/teddsa_addon/addon/src/keygen.rs b/crypto/teddsa/teddsa_addon/addon/src/keygen.rs index 97c14db5e..3a9b36c5b 100644 --- a/crypto/teddsa/teddsa_addon/addon/src/keygen.rs +++ b/crypto/teddsa/teddsa_addon/addon/src/keygen.rs @@ -236,3 +236,70 @@ pub fn napi_reconstruct_key_package_ed25519( Ok(key_package_bytes) } + +/// Reconstruct a public_key_package from verifying_shares, identifiers, and verifying_key. +#[napi] +pub fn napi_reconstruct_public_key_package_ed25519( + client_verifying_share: Vec, + client_identifier: Vec, + server_verifying_share: Vec, + server_identifier: Vec, + verifying_key: Vec, +) -> Result> { + use frost::keys::{PublicKeyPackage, VerifyingShare}; + use frost::Identifier; + use frost::VerifyingKey; + use std::collections::BTreeMap; + + let client_identifier = Identifier::deserialize(&client_identifier).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize client_identifier: {:?}", e), + ) + })?; + + let server_identifier = Identifier::deserialize(&server_identifier).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize server_identifier: {:?}", e), + ) + })?; + + let client_verifying_share = + VerifyingShare::deserialize(&client_verifying_share).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize client_verifying_share: {:?}", e), + ) + })?; + + let server_verifying_share = + VerifyingShare::deserialize(&server_verifying_share).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize server_verifying_share: {:?}", e), + ) + })?; + + let verifying_key = VerifyingKey::deserialize(&verifying_key).map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to deserialize verifying_key: {:?}", e), + ) + })?; + + let mut verifying_shares: BTreeMap = BTreeMap::new(); + verifying_shares.insert(client_identifier, client_verifying_share); + verifying_shares.insert(server_identifier, server_verifying_share); + + let public_key_package = PublicKeyPackage::new(verifying_shares, verifying_key); + + let public_key_package_bytes = public_key_package.serialize().map_err(|e| { + napi::Error::new( + napi::Status::GenericFailure, + format!("Failed to serialize public_key_package: {:?}", e), + ) + })?; + + Ok(public_key_package_bytes) +} diff --git a/crypto/teddsa/teddsa_addon/addon/teddsa-addon.darwin-arm64.node b/crypto/teddsa/teddsa_addon/addon/teddsa-addon.darwin-arm64.node index 92ada7bbcf6a379ac65c9d3f3ddfa3c200e3bdbf..e1abb4b8d8df9c904ea1c6e27c759c2f97e004c3 100755 GIT binary patch delta 129408 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

    Wf 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 MABV#~T?qXD02jqB4gdfE delta 124689 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 Date: Fri, 9 Jan 2026 14:41:25 +0900 Subject: [PATCH 08/17] teddsa_addon: add reconstruct_public_key_package test --- .../teddsa_addon/src/tests/keygen.test.ts | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts b/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts index 3f5fc478d..2c356aba2 100644 --- a/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts +++ b/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts @@ -4,6 +4,7 @@ import { runKeygenCentralizedEd25519, runKeygenImportEd25519, extractKeyPackageSharesEd25519, + reconstructPublicKeyPackageEd25519, } from "../server"; export async function keygenCentralizedTest() { @@ -480,6 +481,189 @@ export async function extractKeyPackageSharesTest() { console.log("\nExtract key package shares test passed"); } +export async function reconstructPublicKeyPackageTest() { + console.log("\nTesting reconstructPublicKeyPackageEd25519...\n"); + + // Generate a keygen output to get the original public_key_package + const keygenOutput = runKeygenCentralizedEd25519(); + const originalPublicKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P0].public_key_package, + ); + + // Extract verifying_shares and identifiers from key_packages + const clientKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P0].key_package, + ); + const serverKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P1].key_package, + ); + + const clientShares = extractKeyPackageSharesEd25519(clientKeyPackage); + const serverShares = extractKeyPackageSharesEd25519(serverKeyPackage); + + const clientIdentifier = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P0].identifier, + ); + const serverIdentifier = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P1].identifier, + ); + const verifyingKey = new Uint8Array(keygenOutput.public_key); + + // Reconstruct public_key_package + const reconstructedPublicKeyPackage = reconstructPublicKeyPackageEd25519( + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + verifyingKey, + ); + + // Validate output structure + if ( + !reconstructedPublicKeyPackage || + reconstructedPublicKeyPackage.length === 0 + ) { + throw new Error("Reconstructed public_key_package is empty"); + } + + console.log( + ` ✓ Public key package reconstructed: ${reconstructedPublicKeyPackage.length} bytes`, + ); + + // Compare with original public_key_package + const originalHex = Buffer.from(originalPublicKeyPackage).toString("hex"); + const reconstructedHex = Buffer.from(reconstructedPublicKeyPackage).toString( + "hex", + ); + + if (originalHex !== reconstructedHex) { + throw new Error( + "Reconstructed public_key_package should match original public_key_package", + ); + } + + console.log(" ✓ Reconstructed public_key_package matches original"); + + // Test consistency: reconstruct multiple times should produce same result + const reconstructed1 = reconstructPublicKeyPackageEd25519( + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + verifyingKey, + ); + const reconstructed2 = reconstructPublicKeyPackageEd25519( + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + verifyingKey, + ); + + const reconstructed1Hex = Buffer.from(reconstructed1).toString("hex"); + const reconstructed2Hex = Buffer.from(reconstructed2).toString("hex"); + + if (reconstructed1Hex !== reconstructed2Hex) { + throw new Error("Reconstruction should be deterministic"); + } + + console.log(" ✓ Reconstruction is deterministic"); + + // Test with invalid verifying_share (wrong length) + try { + const invalidVerifyingShare = new Uint8Array(31).fill(0xff); + reconstructPublicKeyPackageEd25519( + invalidVerifyingShare, + clientIdentifier, + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + verifyingKey, + ); + throw new Error("Should have thrown an error for invalid verifying_share"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid verifying_share: ${error.message}`, + ); + } + console.log(" ✓ Invalid verifying_share correctly rejected"); + } + + // Test with invalid identifier (wrong length) + try { + const invalidIdentifier = new Uint8Array(31).fill(0xff); + reconstructPublicKeyPackageEd25519( + new Uint8Array(clientShares.verifying_share), + invalidIdentifier, + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + verifyingKey, + ); + throw new Error("Should have thrown an error for invalid identifier"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid identifier: ${error.message}`, + ); + } + console.log(" ✓ Invalid identifier correctly rejected"); + } + + // Test with invalid verifying_key (wrong length) + try { + const invalidVerifyingKey = new Uint8Array(31).fill(0xff); + reconstructPublicKeyPackageEd25519( + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + invalidVerifyingKey, + ); + throw new Error("Should have thrown an error for invalid verifying_key"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid verifying_key: ${error.message}`, + ); + } + console.log(" ✓ Invalid verifying_key correctly rejected"); + } + + // Test with swapped identifiers (should produce same result since BTreeMap orders by identifier) + const swappedPublicKeyPackage = reconstructPublicKeyPackageEd25519( + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + verifyingKey, + ); + + const swappedHex = Buffer.from(swappedPublicKeyPackage).toString("hex"); + if (swappedHex !== originalHex) { + throw new Error( + "Swapped identifiers should produce same public_key_package (BTreeMap orders by identifier)", + ); + } + + console.log( + " ✓ Swapped identifiers produce same package (BTreeMap ordering)", + ); + + console.log("\nReconstruct public key package test passed"); +} + // Run the tests async function main() { console.log("Starting Ed25519 keygen tests...\n"); @@ -494,6 +678,7 @@ async function main() { await keygenImportEdgeCasesTest(); await keygenCentralizedConsistencyTest(); await extractKeyPackageSharesTest(); + await reconstructPublicKeyPackageTest(); console.log("\n" + "=".repeat(50)); console.log("All keygen tests passed!"); From 479bbf8edd00bb30e0fe3254710c63ed7193d874 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 14:50:53 +0900 Subject: [PATCH 09/17] teddsa_addon: add reconstruct_key_package test --- .../teddsa_addon/src/tests/keygen.test.ts | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts b/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts index 2c356aba2..8e07204aa 100644 --- a/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts +++ b/crypto/teddsa/teddsa_addon/src/tests/keygen.test.ts @@ -5,6 +5,7 @@ import { runKeygenImportEd25519, extractKeyPackageSharesEd25519, reconstructPublicKeyPackageEd25519, + reconstructKeyPackageEd25519, } from "../server"; export async function keygenCentralizedTest() { @@ -664,6 +665,256 @@ export async function reconstructPublicKeyPackageTest() { console.log("\nReconstruct public key package test passed"); } +export async function reconstructKeyPackageTest() { + console.log("\nTesting reconstructKeyPackageEd25519...\n"); + + // Generate a keygen output to get the original key_package + const keygenOutput = runKeygenCentralizedEd25519(); + const originalClientKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P0].key_package, + ); + const originalServerKeyPackage = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P1].key_package, + ); + + // Extract shares from key_packages + const clientShares = extractKeyPackageSharesEd25519(originalClientKeyPackage); + const serverShares = extractKeyPackageSharesEd25519(originalServerKeyPackage); + + const clientIdentifier = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P0].identifier, + ); + const serverIdentifier = new Uint8Array( + keygenOutput.keygen_outputs[Participant.P1].identifier, + ); + const verifyingKey = new Uint8Array(keygenOutput.public_key); + const minSigners = 2; + + // Reconstruct client key_package + const reconstructedClientKeyPackage = reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + verifyingKey, + minSigners, + ); + + // Validate output structure + if ( + !reconstructedClientKeyPackage || + reconstructedClientKeyPackage.length === 0 + ) { + throw new Error("Reconstructed client key_package is empty"); + } + + console.log( + ` ✓ Client key package reconstructed: ${reconstructedClientKeyPackage.length} bytes`, + ); + + // Compare with original client key_package + const originalClientHex = Buffer.from(originalClientKeyPackage).toString( + "hex", + ); + const reconstructedClientHex = Buffer.from( + reconstructedClientKeyPackage, + ).toString("hex"); + + if (originalClientHex !== reconstructedClientHex) { + throw new Error( + "Reconstructed client key_package should match original client key_package", + ); + } + + console.log(" ✓ Reconstructed client key_package matches original"); + + // Reconstruct server key_package + const reconstructedServerKeyPackage = reconstructKeyPackageEd25519( + new Uint8Array(serverShares.signing_share), + new Uint8Array(serverShares.verifying_share), + serverIdentifier, + verifyingKey, + minSigners, + ); + + // Validate server key_package + if ( + !reconstructedServerKeyPackage || + reconstructedServerKeyPackage.length === 0 + ) { + throw new Error("Reconstructed server key_package is empty"); + } + + const originalServerHex = Buffer.from(originalServerKeyPackage).toString( + "hex", + ); + const reconstructedServerHex = Buffer.from( + reconstructedServerKeyPackage, + ).toString("hex"); + + if (originalServerHex !== reconstructedServerHex) { + throw new Error( + "Reconstructed server key_package should match original server key_package", + ); + } + + console.log(" ✓ Reconstructed server key_package matches original"); + + // Verify client and server key_packages are different + if (reconstructedClientHex === reconstructedServerHex) { + throw new Error( + "Client and server key_packages should be different (different identifiers and shares)", + ); + } + + console.log(" ✓ Client and server key_packages are different"); + + // Test consistency: reconstruct multiple times should produce same result + const reconstructed1 = reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + verifyingKey, + minSigners, + ); + const reconstructed2 = reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + verifyingKey, + minSigners, + ); + + const reconstructed1Hex = Buffer.from(reconstructed1).toString("hex"); + const reconstructed2Hex = Buffer.from(reconstructed2).toString("hex"); + + if (reconstructed1Hex !== reconstructed2Hex) { + throw new Error("Reconstruction should be deterministic"); + } + + console.log(" ✓ Reconstruction is deterministic"); + + // Test with invalid signing_share (wrong length) + try { + const invalidSigningShare = new Uint8Array(31).fill(0xff); + reconstructKeyPackageEd25519( + invalidSigningShare, + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + verifyingKey, + minSigners, + ); + throw new Error("Should have thrown an error for invalid signing_share"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid signing_share: ${error.message}`, + ); + } + console.log(" ✓ Invalid signing_share correctly rejected"); + } + + // Test with invalid verifying_share (wrong length) + try { + const invalidVerifyingShare = new Uint8Array(31).fill(0xff); + reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + invalidVerifyingShare, + clientIdentifier, + verifyingKey, + minSigners, + ); + throw new Error("Should have thrown an error for invalid verifying_share"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid verifying_share: ${error.message}`, + ); + } + console.log(" ✓ Invalid verifying_share correctly rejected"); + } + + // Test with invalid identifier (wrong length) + try { + const invalidIdentifier = new Uint8Array(31).fill(0xff); + reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + new Uint8Array(clientShares.verifying_share), + invalidIdentifier, + verifyingKey, + minSigners, + ); + throw new Error("Should have thrown an error for invalid identifier"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid identifier: ${error.message}`, + ); + } + console.log(" ✓ Invalid identifier correctly rejected"); + } + + // Test with invalid verifying_key (wrong length) + try { + const invalidVerifyingKey = new Uint8Array(31).fill(0xff); + reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + new Uint8Array(clientShares.verifying_share), + clientIdentifier, + invalidVerifyingKey, + minSigners, + ); + throw new Error("Should have thrown an error for invalid verifying_key"); + } catch (error: any) { + if ( + !error.message?.includes("deserialize") && + !error.message?.includes("Failed to deserialize") && + !error.message?.includes("Invalid") + ) { + throw new Error( + `Unexpected error for invalid verifying_key: ${error.message}`, + ); + } + console.log(" ✓ Invalid verifying_key correctly rejected"); + } + + const mismatchedKeyPackage = reconstructKeyPackageEd25519( + new Uint8Array(clientShares.signing_share), + new Uint8Array(clientShares.verifying_share), + serverIdentifier, // Using server identifier with client shares + verifyingKey, + minSigners, + ); + + if (mismatchedKeyPackage.length === 0) { + throw new Error( + "Mismatched components should still produce valid key_package", + ); + } + + const mismatchedHex = Buffer.from(mismatchedKeyPackage).toString("hex"); + if (mismatchedHex === originalClientHex) { + throw new Error( + "Mismatched identifier should produce different key_package", + ); + } + + console.log(" ✓ Mismatched components produce different key_package"); + + console.log("\nReconstruct key package test passed"); +} + // Run the tests async function main() { console.log("Starting Ed25519 keygen tests...\n"); @@ -678,6 +929,7 @@ async function main() { await keygenImportEdgeCasesTest(); await keygenCentralizedConsistencyTest(); await extractKeyPackageSharesTest(); + await reconstructKeyPackageTest(); await reconstructPublicKeyPackageTest(); console.log("\n" + "=".repeat(50)); From e2c736bbc7a7f0dbeb587b10b6da9cd341f6b298 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 16:18:39 +0900 Subject: [PATCH 10/17] tss_api: refactor sign_ed25519_aggregate --- backend/tss_api/src/api/sign_ed25519/index.ts | 60 +++++++++++++++++-- backend/tss_api/src/routes/sign_ed25519.ts | 13 +++- common/oko_types/src/tss/sign_ed25519.ts | 2 + 3 files changed, 68 insertions(+), 7 deletions(-) diff --git a/backend/tss_api/src/api/sign_ed25519/index.ts b/backend/tss_api/src/api/sign_ed25519/index.ts index baff1e428..d25f286b8 100644 --- a/backend/tss_api/src/api/sign_ed25519/index.ts +++ b/backend/tss_api/src/api/sign_ed25519/index.ts @@ -29,6 +29,7 @@ import { runSignRound2Ed25519, runAggregateEd25519, reconstructKeyPackageEd25519, + reconstructPublicKeyPackageEd25519, } from "@oko-wallet/teddsa-addon/src/server"; import { Participant, @@ -501,8 +502,14 @@ export async function runSignEd25519Aggregate( request: SignEd25519AggregateRequest, ): Promise> { try { - const { email, wallet_id, msg, all_commitments, all_signature_shares } = - request; + const { + email, + wallet_id, + msg, + all_commitments, + all_signature_shares, + user_verifying_share, + } = request; const validateWalletEmailRes = await validateWalletEmail( db, @@ -526,11 +533,52 @@ export async function runSignEd25519Aggregate( }; } - // @TODO: Implement public_key_package reconstruction + // Decrypt stored shares + const encryptedShare = wallet.enc_tss_share.toString("utf-8"); + const decryptedShare = await decryptDataAsync( + encryptedShare, + encryptionSecret, + ); + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; + }; + + // Reconstruct public_key_package from user and server verifying_shares + const userIdentifier = participantToIdentifier(Participant.P0); + const serverIdentifier = participantToIdentifier(Participant.P1); + const verifyingKey = Array.from(wallet.public_key); + + let publicKeyPackageBytes: Uint8Array; + try { + publicKeyPackageBytes = reconstructPublicKeyPackageEd25519( + new Uint8Array(user_verifying_share), + new Uint8Array(userIdentifier), + new Uint8Array(storedShares.verifying_share), + new Uint8Array(serverIdentifier), + new Uint8Array(verifyingKey), + ); + } catch (error) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to reconstruct public_key_package: ${error instanceof Error ? error.message : String(error)}`, + }; + } + + // Aggregate signature + const aggregateResult = runAggregateEd25519( + new Uint8Array(msg), + all_commitments, + all_signature_shares, + publicKeyPackageBytes, + ); + return { - success: false, - code: "UNKNOWN_ERROR", - msg: "public_key_package reconstruction not yet implemented. Please store public_key_package separately in wallet or require it in the request.", + success: true, + data: { + signature: aggregateResult.signature, + }, }; } catch (error) { return { diff --git a/backend/tss_api/src/routes/sign_ed25519.ts b/backend/tss_api/src/routes/sign_ed25519.ts index 54374cf57..904c21a1e 100644 --- a/backend/tss_api/src/routes/sign_ed25519.ts +++ b/backend/tss_api/src/routes/sign_ed25519.ts @@ -392,8 +392,18 @@ export function setSignEd25519Routes(router: Router) { }, }, }, + user_verifying_share: { + type: "array", + items: { type: "number" }, + description: "P0's verifying_share (32 bytes)", + }, }, - required: ["msg", "all_commitments", "all_signature_shares"], + required: [ + "msg", + "all_commitments", + "all_signature_shares", + "user_verifying_share", + ], }, }, }, @@ -450,6 +460,7 @@ export function setSignEd25519Routes(router: Router) { msg: body.msg, all_commitments: body.all_commitments, all_signature_shares: body.all_signature_shares, + user_verifying_share: body.user_verifying_share, }, ); diff --git a/common/oko_types/src/tss/sign_ed25519.ts b/common/oko_types/src/tss/sign_ed25519.ts index 4a28f1445..fdc6be486 100644 --- a/common/oko_types/src/tss/sign_ed25519.ts +++ b/common/oko_types/src/tss/sign_ed25519.ts @@ -41,6 +41,7 @@ export interface SignEd25519AggregateRequest { msg: number[]; all_commitments: CommitmentEntry[]; all_signature_shares: SignatureShareEntry[]; + user_verifying_share: number[]; // P0's verifying_share (32 bytes) } export interface SignEd25519AggregateResponse { @@ -51,6 +52,7 @@ export type SignEd25519AggregateBody = { msg: number[]; all_commitments: CommitmentEntry[]; all_signature_shares: SignatureShareEntry[]; + user_verifying_share: number[]; }; export interface SignEd25519ServerState { From 2e48267efcff420a9df126d760ebe83ed9f7d999 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 17:29:08 +0900 Subject: [PATCH 11/17] tss_api: refactor sign_ed25519 test --- .../src/api/sign_ed25519/index.test.ts | 1451 +++++++++-------- 1 file changed, 740 insertions(+), 711 deletions(-) diff --git a/backend/tss_api/src/api/sign_ed25519/index.test.ts b/backend/tss_api/src/api/sign_ed25519/index.test.ts index 3ea8ebd46..14a143a1e 100644 --- a/backend/tss_api/src/api/sign_ed25519/index.test.ts +++ b/backend/tss_api/src/api/sign_ed25519/index.test.ts @@ -1,711 +1,740 @@ -// TODO: refactor this tests @chemonoworld - -// import { jest } from "@jest/globals"; -// import { Pool } from "pg"; -// import type { -// SignEd25519Round1Request, -// SignEd25519Round2Request, -// SignEd25519AggregateRequest, -// } from "@oko-wallet/oko-types/tss"; -// import type { TeddsaKeygenOutput } from "@oko-wallet/teddsa-interface"; -// import { Participant } from "@oko-wallet/teddsa-interface"; -// import { -// runKeygenCentralizedEd25519, -// runSignRound1Ed25519 as clientRunSignRound1Ed25519, -// runSignRound2Ed25519 as clientRunSignRound2Ed25519, -// runAggregateEd25519 as clientRunAggregateEd25519, -// runVerifyEd25519, -// } from "@oko-wallet/teddsa-addon/src/server"; -// import { createPgConn } from "@oko-wallet/postgres-lib"; -// import type { WalletStatus } from "@oko-wallet/oko-types/wallets"; -// import { insertKSNode } from "@oko-wallet/oko-pg-interface/ks_nodes"; -// import { createWallet } from "@oko-wallet/oko-pg-interface/oko_wallets"; -// import { createUser } from "@oko-wallet/oko-pg-interface/oko_users"; -// import { insertKeyShareNodeMeta } from "@oko-wallet/oko-pg-interface/key_share_node_meta"; -// import { insertCustomer } from "@oko-wallet/oko-pg-interface/customers"; -// import { encryptDataAsync } from "@oko-wallet/crypto-js/node"; - -// import { resetPgDatabase } from "@oko-wallet-tss-api/testing/database"; -// import { testPgConfig } from "@oko-wallet-tss-api/database/test_config"; -// import { -// runSignEd25519Round1, -// runSignEd25519Round2, -// runSignEd25519Aggregate, -// } from "@oko-wallet-tss-api/api/sign_ed25519"; -// import { TEMP_ENC_SECRET } from "@oko-wallet-tss-api/api/utils"; - -// const SSS_THRESHOLD = 2; -// const TEST_EMAIL = "test-ed25519@test.com"; - -// interface TestSetupResult { -// pool: Pool; -// walletId: string; -// customerId: string; -// clientKeygenOutput: TeddsaKeygenOutput; -// serverKeygenOutput: TeddsaKeygenOutput; -// } - -// async function setUpKSNodes(pool: Pool): Promise { -// const ksNodeNames = ["ksNode1", "ksNode2"]; -// const ksNodeIds = []; -// const createKSNodesRes = await Promise.all( -// ksNodeNames.map((ksNodeName) => -// insertKSNode(pool, ksNodeName, `http://test.com/${ksNodeName}`), -// ), -// ); -// for (const res of createKSNodesRes) { -// if (res.success === false) { -// throw new Error("Failed to create ks nodes"); -// } -// ksNodeIds.push(res.data.node_id); -// } -// return ksNodeIds; -// } - -// async function setUpEd25519Wallet(pool: Pool): Promise { -// // Generate keys using centralized keygen -// const keygenResult = runKeygenCentralizedEd25519(); -// const clientKeygenOutput = keygenResult.keygen_outputs[Participant.P0]; -// const serverKeygenOutput = keygenResult.keygen_outputs[Participant.P1]; - -// // Set up KS nodes and metadata -// const ksNodeIds = await setUpKSNodes(pool); -// await insertKeyShareNodeMeta(pool, { -// sss_threshold: SSS_THRESHOLD, -// }); - -// // Create customer -// const customerId = crypto.randomUUID(); -// const insertCustomerRes = await insertCustomer(pool, { -// customer_id: customerId, -// label: "test-customer", -// status: "ACTIVE", -// url: null, -// logo_url: null, -// theme: "dark", -// }); -// if (insertCustomerRes.success === false) { -// throw new Error(`Failed to create customer: ${insertCustomerRes.err}`); -// } - -// // Create user -// const createUserRes = await createUser(pool, TEST_EMAIL, "google"); -// if (createUserRes.success === false) { -// throw new Error(`Failed to create user: ${createUserRes.err}`); -// } -// const userId = createUserRes.data.user_id; - -// // Encrypt server key package -// const serverKeyPackageJson = JSON.stringify(serverKeygenOutput); -// const encryptedShare = await encryptDataAsync( -// serverKeyPackageJson, -// TEMP_ENC_SECRET, -// ); - -// // Create Ed25519 wallet -// const createWalletRes = await createWallet(pool, { -// user_id: userId, -// curve_type: "ed25519", -// public_key: Buffer.from(keygenResult.public_key), -// enc_tss_share: Buffer.from(encryptedShare, "utf-8"), -// sss_threshold: SSS_THRESHOLD, -// status: "ACTIVE" as WalletStatus, -// }); -// if (createWalletRes.success === false) { -// throw new Error(`Failed to create wallet: ${createWalletRes.err}`); -// } -// const walletId = createWalletRes.data.wallet_id; - -// return { -// pool, -// walletId, -// customerId, -// clientKeygenOutput, -// serverKeygenOutput, -// }; -// } - -// describe("Ed25519 Signing", () => { -// let pool: Pool; - -// beforeAll(async () => { -// const config = testPgConfig; -// const createPostgresRes = await createPgConn({ -// database: config.database, -// host: config.host, -// password: config.password, -// user: config.user, -// port: config.port, -// ssl: config.ssl, -// }); - -// if (createPostgresRes.success === false) { -// console.error(createPostgresRes.err); -// throw new Error("Failed to create postgres database"); -// } - -// pool = createPostgresRes.data; -// }); - -// afterAll(async () => { -// await pool.end(); -// }); - -// beforeEach(async () => { -// await resetPgDatabase(pool); -// }); - -// describe("runSignEd25519Round1", () => { -// it("should generate commitments successfully", async () => { -// const { walletId, customerId } = await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message"); - -// const request: SignEd25519Round1Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...testMessage], -// }; - -// const result = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, request); - -// expect(result.success).toBe(true); -// if (result.success) { -// expect(result.data.session_id).toBeDefined(); -// expect(result.data.commitments_0).toBeDefined(); -// expect(result.data.commitments_0.identifier).toBeDefined(); -// expect(result.data.commitments_0.commitments).toBeDefined(); -// expect(Array.isArray(result.data.commitments_0.identifier)).toBe(true); -// expect(Array.isArray(result.data.commitments_0.commitments)).toBe(true); -// } -// }); - -// it("should fail with invalid email", async () => { -// const { walletId, customerId } = await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message"); - -// const request: SignEd25519Round1Request = { -// email: "wrong@test.com", -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...testMessage], -// }; - -// const result = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, request); - -// expect(result.success).toBe(false); -// if (!result.success) { -// expect(result.code).toBe("UNAUTHORIZED"); -// } -// }); - -// it("should fail with invalid wallet_id", async () => { -// const { customerId } = await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message"); - -// const request: SignEd25519Round1Request = { -// email: TEST_EMAIL, -// wallet_id: "00000000-0000-0000-0000-000000000000", -// customer_id: customerId, -// msg: [...testMessage], -// }; - -// const result = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, request); - -// expect(result.success).toBe(false); -// if (!result.success) { -// expect(result.code).toBe("UNAUTHORIZED"); -// } -// }); -// }); - -// describe("runSignEd25519Round2", () => { -// it("should generate signature share successfully", async () => { -// const { walletId, customerId, clientKeygenOutput } = -// await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message for Ed25519"); - -// // Round 1: Get server commitments -// const round1Request: SignEd25519Round1Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...testMessage], -// }; -// const round1Result = await runSignEd25519Round1( -// pool, -// TEMP_ENC_SECRET, -// round1Request, -// ); -// expect(round1Result.success).toBe(true); -// if (!round1Result.success) throw new Error("Round 1 failed"); - -// // Client generates their round 1 output -// const clientRound1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); - -// // Round 2: Get server signature share -// const round2Request: SignEd25519Round2Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: round1Result.data.session_id, -// commitments_1: { -// identifier: clientRound1.identifier, -// commitments: clientRound1.commitments, -// }, -// }; -// const round2Result = await runSignEd25519Round2( -// pool, -// TEMP_ENC_SECRET, -// round2Request, -// ); - -// expect(round2Result.success).toBe(true); -// if (round2Result.success) { -// expect(round2Result.data.signature_share_0).toBeDefined(); -// expect(round2Result.data.signature_share_0.identifier).toBeDefined(); -// expect( -// round2Result.data.signature_share_0.signature_share, -// ).toBeDefined(); -// } -// }); - -// it("should fail with invalid session_id", async () => { -// const { walletId, customerId, clientKeygenOutput } = -// await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message"); - -// const clientRound1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); - -// const round2Request: SignEd25519Round2Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: "00000000-0000-0000-0000-000000000000", -// commitments_1: { -// identifier: clientRound1.identifier, -// commitments: clientRound1.commitments, -// }, -// }; -// const result = await runSignEd25519Round2( -// pool, -// TEMP_ENC_SECRET, -// round2Request, -// ); - -// expect(result.success).toBe(false); -// if (!result.success) { -// expect(result.code).toBe("INVALID_TSS_SESSION"); -// } -// }); - -// it("should fail when Round2 is called twice (duplicate call prevention)", async () => { -// const { walletId, customerId, clientKeygenOutput } = -// await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message"); - -// // Round 1: Get server commitments -// const round1Request: SignEd25519Round1Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...testMessage], -// }; -// const round1Result = await runSignEd25519Round1( -// pool, -// TEMP_ENC_SECRET, -// round1Request, -// ); -// expect(round1Result.success).toBe(true); -// if (!round1Result.success) throw new Error("Round 1 failed"); - -// const clientRound1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); - -// // First Round 2 call - should succeed -// const round2Request: SignEd25519Round2Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: round1Result.data.session_id, -// commitments_1: { -// identifier: clientRound1.identifier, -// commitments: clientRound1.commitments, -// }, -// }; -// const round2Result = await runSignEd25519Round2( -// pool, -// TEMP_ENC_SECRET, -// round2Request, -// ); -// expect(round2Result.success).toBe(true); - -// // Second Round 2 call with same session - should fail -// const duplicateRound2Result = await runSignEd25519Round2( -// pool, -// TEMP_ENC_SECRET, -// round2Request, -// ); - -// expect(duplicateRound2Result.success).toBe(false); -// if (!duplicateRound2Result.success) { -// expect(duplicateRound2Result.code).toBe("INVALID_TSS_SESSION"); -// } -// }); - -// it("should fail when using COMPLETED session for Round2", async () => { -// const { walletId, customerId, clientKeygenOutput } = -// await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message for signing"); - -// // Complete full signing flow first -// const round1Res = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, { -// email: TEST_EMAIL, -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...testMessage], -// }); -// expect(round1Res.success).toBe(true); -// if (!round1Res.success) throw new Error("Round 1 failed"); - -// const clientR1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); - -// const allCommitments = [ -// { identifier: clientR1.identifier, commitments: clientR1.commitments }, -// { -// identifier: round1Res.data.commitments_0.identifier, -// commitments: round1Res.data.commitments_0.commitments, -// }, -// ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - -// const round2Res = await runSignEd25519Round2(pool, TEMP_ENC_SECRET, { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: round1Res.data.session_id, -// commitments_1: { -// identifier: clientR1.identifier, -// commitments: clientR1.commitments, -// }, -// }); -// expect(round2Res.success).toBe(true); -// if (!round2Res.success) throw new Error("Round 2 failed"); - -// const clientR2 = clientRunSignRound2Ed25519( -// testMessage, -// new Uint8Array(clientKeygenOutput.key_package), -// new Uint8Array(clientR1.nonces), -// allCommitments, -// ); - -// const allShares = [ -// { -// identifier: clientR2.identifier, -// signature_share: clientR2.signature_share, -// }, -// { -// identifier: round2Res.data.signature_share_0.identifier, -// signature_share: round2Res.data.signature_share_0.signature_share, -// }, -// ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - -// // Complete the signing with Aggregate -// const aggRes = await runSignEd25519Aggregate(pool, TEMP_ENC_SECRET, { -// email: TEST_EMAIL, -// wallet_id: walletId, -// msg: [...testMessage], -// all_commitments: allCommitments, -// all_signature_shares: allShares, -// }); -// expect(aggRes.success).toBe(true); - -// // Now try to use the COMPLETED session for Round2 - should fail -// const newClientR1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); -// const replayRound2Res = await runSignEd25519Round2( -// pool, -// TEMP_ENC_SECRET, -// { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: round1Res.data.session_id, // Reusing completed session -// commitments_1: { -// identifier: newClientR1.identifier, -// commitments: newClientR1.commitments, -// }, -// }, -// ); - -// expect(replayRound2Res.success).toBe(false); -// if (!replayRound2Res.success) { -// expect(replayRound2Res.code).toBe("INVALID_TSS_SESSION"); -// } -// }); -// }); - -// describe("runSignEd25519Aggregate", () => { -// it("should aggregate signatures and produce valid signature", async () => { -// const { walletId, customerId, clientKeygenOutput, serverKeygenOutput } = -// await setUpEd25519Wallet(pool); -// const testMessage = new TextEncoder().encode("Test message for signing"); - -// // Round 1: Both parties generate commitments -// const round1Request: SignEd25519Round1Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...testMessage], -// }; -// const serverRound1Result = await runSignEd25519Round1( -// pool, -// TEMP_ENC_SECRET, -// round1Request, -// ); -// expect(serverRound1Result.success).toBe(true); -// if (!serverRound1Result.success) throw new Error("Server Round 1 failed"); - -// const clientRound1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); - -// // Collect all commitments (sorted by identifier) -// const allCommitments = [ -// { -// identifier: clientRound1.identifier, -// commitments: clientRound1.commitments, -// }, -// { -// identifier: serverRound1Result.data.commitments_0.identifier, -// commitments: serverRound1Result.data.commitments_0.commitments, -// }, -// ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - -// // Round 2: Both parties generate signature shares -// const round2Request: SignEd25519Round2Request = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: serverRound1Result.data.session_id, -// commitments_1: { -// identifier: clientRound1.identifier, -// commitments: clientRound1.commitments, -// }, -// }; -// const serverRound2Result = await runSignEd25519Round2( -// pool, -// TEMP_ENC_SECRET, -// round2Request, -// ); -// expect(serverRound2Result.success).toBe(true); -// if (!serverRound2Result.success) throw new Error("Server Round 2 failed"); - -// const clientRound2 = clientRunSignRound2Ed25519( -// testMessage, -// new Uint8Array(clientKeygenOutput.key_package), -// new Uint8Array(clientRound1.nonces), -// allCommitments, -// ); - -// // Collect all signature shares (sorted by identifier) -// const allSignatureShares = [ -// { -// identifier: clientRound2.identifier, -// signature_share: clientRound2.signature_share, -// }, -// { -// identifier: serverRound2Result.data.signature_share_0.identifier, -// signature_share: -// serverRound2Result.data.signature_share_0.signature_share, -// }, -// ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - -// // Aggregate -// const aggregateRequest: SignEd25519AggregateRequest = { -// email: TEST_EMAIL, -// wallet_id: walletId, -// msg: [...testMessage], -// all_commitments: allCommitments, -// all_signature_shares: allSignatureShares, -// }; -// const aggregateResult = await runSignEd25519Aggregate( -// pool, -// TEMP_ENC_SECRET, -// aggregateRequest, -// ); - -// expect(aggregateResult.success).toBe(true); -// if (aggregateResult.success) { -// expect(aggregateResult.data.signature).toBeDefined(); -// expect(aggregateResult.data.signature.length).toBe(64); - -// // Verify the signature -// const isValid = runVerifyEd25519( -// testMessage, -// new Uint8Array(aggregateResult.data.signature), -// new Uint8Array(clientKeygenOutput.public_key_package), -// ); -// expect(isValid).toBe(true); -// } -// }); - -// it("should fail with wrong wallet type", async () => { -// // Create a secp256k1 wallet instead of ed25519 -// await setUpKSNodes(pool); -// await insertKeyShareNodeMeta(pool, { sss_threshold: SSS_THRESHOLD }); - -// const createUserRes = await createUser(pool, TEST_EMAIL, "google"); -// if (!createUserRes.success) throw new Error("Failed to create user"); - -// const encryptedShare = await encryptDataAsync( -// JSON.stringify({ private_share: "test", public_key: "test" }), -// TEMP_ENC_SECRET, -// ); - -// const createWalletRes = await createWallet(pool, { -// user_id: createUserRes.data.user_id, -// curve_type: "secp256k1", -// public_key: Buffer.from("03" + "00".repeat(32), "hex"), -// enc_tss_share: Buffer.from(encryptedShare, "utf-8"), -// sss_threshold: SSS_THRESHOLD, -// status: "ACTIVE" as WalletStatus, -// }); -// if (!createWalletRes.success) throw new Error("Failed to create wallet"); - -// const aggregateRequest: SignEd25519AggregateRequest = { -// email: TEST_EMAIL, -// wallet_id: createWalletRes.data.wallet_id, -// msg: [1, 2, 3], -// all_commitments: [], -// all_signature_shares: [], -// }; - -// const result = await runSignEd25519Aggregate( -// pool, -// TEMP_ENC_SECRET, -// aggregateRequest, -// ); - -// expect(result.success).toBe(false); -// if (!result.success) { -// expect(result.code).toBe("INVALID_WALLET_TYPE"); -// } -// }); - -// it("should fail with invalid wallet_id", async () => { -// await setUpEd25519Wallet(pool); - -// const aggregateRequest: SignEd25519AggregateRequest = { -// email: TEST_EMAIL, -// wallet_id: "00000000-0000-0000-0000-000000000000", -// msg: [1, 2, 3], -// all_commitments: [], -// all_signature_shares: [], -// }; - -// const result = await runSignEd25519Aggregate( -// pool, -// TEMP_ENC_SECRET, -// aggregateRequest, -// ); - -// expect(result.success).toBe(false); -// if (!result.success) { -// expect(result.code).toBe("UNAUTHORIZED"); -// } -// }); -// }); - -// describe("Full signing flow", () => { -// it("should complete full signing flow with valid signature verification", async () => { -// const { walletId, customerId, clientKeygenOutput } = -// await setUpEd25519Wallet(pool); -// const messages = [ -// "Hello, Solana!", -// "Transaction data", -// "Another message to sign", -// ]; - -// for (const msgStr of messages) { -// const message = new TextEncoder().encode(msgStr); - -// // Round 1 -// const round1Res = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, { -// email: TEST_EMAIL, -// wallet_id: walletId, -// customer_id: customerId, -// msg: [...message], -// }); -// expect(round1Res.success).toBe(true); -// if (!round1Res.success) continue; - -// const clientR1 = clientRunSignRound1Ed25519( -// new Uint8Array(clientKeygenOutput.key_package), -// ); - -// const allCommitments = [ -// { -// identifier: clientR1.identifier, -// commitments: clientR1.commitments, -// }, -// { -// identifier: round1Res.data.commitments_0.identifier, -// commitments: round1Res.data.commitments_0.commitments, -// }, -// ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - -// // Round 2 -// const round2Res = await runSignEd25519Round2(pool, TEMP_ENC_SECRET, { -// email: TEST_EMAIL, -// wallet_id: walletId, -// session_id: round1Res.data.session_id, -// commitments_1: { -// identifier: clientR1.identifier, -// commitments: clientR1.commitments, -// }, -// }); -// expect(round2Res.success).toBe(true); -// if (!round2Res.success) continue; - -// const clientR2 = clientRunSignRound2Ed25519( -// message, -// new Uint8Array(clientKeygenOutput.key_package), -// new Uint8Array(clientR1.nonces), -// allCommitments, -// ); - -// const allShares = [ -// { -// identifier: clientR2.identifier, -// signature_share: clientR2.signature_share, -// }, -// { -// identifier: round2Res.data.signature_share_0.identifier, -// signature_share: round2Res.data.signature_share_0.signature_share, -// }, -// ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - -// // Aggregate -// const aggRes = await runSignEd25519Aggregate(pool, TEMP_ENC_SECRET, { -// email: TEST_EMAIL, -// wallet_id: walletId, -// msg: [...message], -// all_commitments: allCommitments, -// all_signature_shares: allShares, -// }); -// expect(aggRes.success).toBe(true); -// if (!aggRes.success) continue; - -// // Verify -// const isValid = runVerifyEd25519( -// message, -// new Uint8Array(aggRes.data.signature), -// new Uint8Array(clientKeygenOutput.public_key_package), -// ); -// expect(isValid).toBe(true); -// } -// }); -// }); -// }); +import { Pool } from "pg"; +import type { + SignEd25519Round1Request, + SignEd25519Round2Request, + SignEd25519AggregateRequest, +} from "@oko-wallet/oko-types/tss"; +import { Participant } from "@oko-wallet/teddsa-interface"; +import { + runKeygenCentralizedEd25519, + runSignRound1Ed25519 as clientRunSignRound1Ed25519, + runSignRound2Ed25519 as clientRunSignRound2Ed25519, + runVerifyEd25519, + extractKeyPackageSharesEd25519, +} from "@oko-wallet/teddsa-addon/src/server"; +import { createPgConn } from "@oko-wallet/postgres-lib"; +import type { WalletStatus } from "@oko-wallet/oko-types/wallets"; +import { insertKSNode } from "@oko-wallet/oko-pg-interface/ks_nodes"; +import { createWallet } from "@oko-wallet/oko-pg-interface/oko_wallets"; +import { createUser } from "@oko-wallet/oko-pg-interface/oko_users"; +import { insertKeyShareNodeMeta } from "@oko-wallet/oko-pg-interface/key_share_node_meta"; +import { insertCustomer } from "@oko-wallet/oko-pg-interface/customers"; +import { encryptDataAsync } from "@oko-wallet/crypto-js/node"; + +import { resetPgDatabase } from "@oko-wallet-tss-api/testing/database"; +import { testPgConfig } from "@oko-wallet-tss-api/database/test_config"; +import { + runSignEd25519Round1, + runSignEd25519Round2, + runSignEd25519Aggregate, +} from "@oko-wallet-tss-api/api/sign_ed25519"; +import { TEMP_ENC_SECRET } from "@oko-wallet-tss-api/api/utils"; + +const SSS_THRESHOLD = 2; +const TEST_EMAIL = "test-ed25519@test.com"; + +interface TestSetupResult { + pool: Pool; + walletId: string; + customerId: string; + clientKeygenOutput: ReturnType< + typeof runKeygenCentralizedEd25519 + >["keygen_outputs"][Participant.P0]; + serverKeygenOutput: ReturnType< + typeof runKeygenCentralizedEd25519 + >["keygen_outputs"][Participant.P1]; +} + +async function setUpKSNodes(pool: Pool): Promise { + const ksNodeNames = ["ksNode1", "ksNode2"]; + const ksNodeIds = []; + const createKSNodesRes = await Promise.all( + ksNodeNames.map((ksNodeName) => + insertKSNode(pool, ksNodeName, `http://test.com/${ksNodeName}`), + ), + ); + for (const res of createKSNodesRes) { + if (res.success === false) { + throw new Error("Failed to create ks nodes"); + } + ksNodeIds.push(res.data.node_id); + } + return ksNodeIds; +} + +async function setUpEd25519Wallet(pool: Pool): Promise { + // Generate keys using centralized keygen + const keygenResult = runKeygenCentralizedEd25519(); + const clientKeygenOutput = keygenResult.keygen_outputs[Participant.P0]; + const serverKeygenOutput = keygenResult.keygen_outputs[Participant.P1]; + + // Set up KS nodes and metadata + const ksNodeIds = await setUpKSNodes(pool); + await insertKeyShareNodeMeta(pool, { + sss_threshold: SSS_THRESHOLD, + }); + + // Create customer + const customerId = crypto.randomUUID(); + const insertCustomerRes = await insertCustomer(pool, { + customer_id: customerId, + label: "test-customer", + status: "ACTIVE", + url: null, + logo_url: null, + theme: "dark", + }); + if (insertCustomerRes.success === false) { + throw new Error(`Failed to create customer: ${insertCustomerRes.err}`); + } + + // Create user + const createUserRes = await createUser(pool, TEST_EMAIL, "google"); + if (createUserRes.success === false) { + throw new Error(`Failed to create user: ${createUserRes.err}`); + } + const userId = createUserRes.data.user_id; + + // Extract signing_share and verifying_share from server key_package + const serverKeyPackageShares = extractKeyPackageSharesEd25519( + new Uint8Array(serverKeygenOutput.key_package), + ); + + // Store only signing_share and verifying_share (64 bytes total) + const sharesData = { + signing_share: serverKeyPackageShares.signing_share, + verifying_share: serverKeyPackageShares.verifying_share, + }; + + const encryptedShare = await encryptDataAsync( + JSON.stringify(sharesData), + TEMP_ENC_SECRET, + ); + + // Create Ed25519 wallet + const createWalletRes = await createWallet(pool, { + user_id: userId, + curve_type: "ed25519", + public_key: Buffer.from(keygenResult.public_key), + enc_tss_share: Buffer.from(encryptedShare, "utf-8"), + sss_threshold: SSS_THRESHOLD, + status: "ACTIVE" as WalletStatus, + }); + if (createWalletRes.success === false) { + throw new Error(`Failed to create wallet: ${createWalletRes.err}`); + } + const walletId = createWalletRes.data.wallet_id; + + return { + pool, + walletId, + customerId, + clientKeygenOutput, + serverKeygenOutput, + }; +} + +describe("Ed25519 Signing", () => { + let pool: Pool; + + beforeAll(async () => { + const config = testPgConfig; + const createPostgresRes = await createPgConn({ + database: config.database, + host: config.host, + password: config.password, + user: config.user, + port: config.port, + ssl: config.ssl, + }); + + if (createPostgresRes.success === false) { + console.error(createPostgresRes.err); + throw new Error("Failed to create postgres database"); + } + + pool = createPostgresRes.data; + }); + + afterAll(async () => { + await pool.end(); + }); + + beforeEach(async () => { + await resetPgDatabase(pool); + }); + + describe("runSignEd25519Round1", () => { + it("should generate commitments successfully", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message"); + + const request: SignEd25519Round1Request = { + email: TEST_EMAIL, + wallet_id: walletId, + customer_id: customerId, + msg: [...testMessage], + }; + + const result = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.session_id).toBeDefined(); + expect(result.data.commitments_0).toBeDefined(); + expect(result.data.commitments_0.identifier).toBeDefined(); + expect(result.data.commitments_0.commitments).toBeDefined(); + expect(Array.isArray(result.data.commitments_0.identifier)).toBe(true); + expect(Array.isArray(result.data.commitments_0.commitments)).toBe(true); + } + }); + + it("should fail with invalid email", async () => { + const { walletId, customerId } = await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message"); + + const request: SignEd25519Round1Request = { + email: "wrong@test.com", + wallet_id: walletId, + customer_id: customerId, + msg: [...testMessage], + }; + + const result = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("UNAUTHORIZED"); + } + }); + + it("should fail with invalid wallet_id", async () => { + const { customerId } = await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message"); + + const request: SignEd25519Round1Request = { + email: TEST_EMAIL, + wallet_id: "00000000-0000-0000-0000-000000000000", + customer_id: customerId, + msg: [...testMessage], + }; + + const result = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, request); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("UNAUTHORIZED"); + } + }); + }); + + describe("runSignEd25519Round2", () => { + it("should generate signature share successfully", async () => { + const { walletId, customerId, clientKeygenOutput } = + await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message for Ed25519"); + + // Round 1: Get server commitments + const round1Request: SignEd25519Round1Request = { + email: TEST_EMAIL, + wallet_id: walletId, + customer_id: customerId, + msg: [...testMessage], + }; + const round1Result = await runSignEd25519Round1( + pool, + TEMP_ENC_SECRET, + round1Request, + ); + expect(round1Result.success).toBe(true); + if (!round1Result.success) throw new Error("Round 1 failed"); + + // Client generates their round 1 output + const clientRound1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + // Round 2: Get server signature share + const round2Request: SignEd25519Round2Request = { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: round1Result.data.session_id, + commitments_1: { + identifier: clientRound1.identifier, + commitments: clientRound1.commitments, + }, + }; + const round2Result = await runSignEd25519Round2( + pool, + TEMP_ENC_SECRET, + round2Request, + ); + + expect(round2Result.success).toBe(true); + if (round2Result.success) { + expect(round2Result.data.signature_share_0).toBeDefined(); + expect(round2Result.data.signature_share_0.identifier).toBeDefined(); + expect( + round2Result.data.signature_share_0.signature_share, + ).toBeDefined(); + } + }); + + it("should fail with invalid session_id", async () => { + const { walletId, customerId, clientKeygenOutput } = + await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message"); + + const clientRound1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + const round2Request: SignEd25519Round2Request = { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: "00000000-0000-0000-0000-000000000000", + commitments_1: { + identifier: clientRound1.identifier, + commitments: clientRound1.commitments, + }, + }; + const result = await runSignEd25519Round2( + pool, + TEMP_ENC_SECRET, + round2Request, + ); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("INVALID_TSS_SESSION"); + } + }); + + it("should fail when Round2 is called twice (duplicate call prevention)", async () => { + const { walletId, customerId, clientKeygenOutput } = + await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message"); + + // Round 1: Get server commitments + const round1Request: SignEd25519Round1Request = { + email: TEST_EMAIL, + wallet_id: walletId, + customer_id: customerId, + msg: [...testMessage], + }; + const round1Result = await runSignEd25519Round1( + pool, + TEMP_ENC_SECRET, + round1Request, + ); + expect(round1Result.success).toBe(true); + if (!round1Result.success) throw new Error("Round 1 failed"); + + const clientRound1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + // First Round 2 call - should succeed + const round2Request: SignEd25519Round2Request = { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: round1Result.data.session_id, + commitments_1: { + identifier: clientRound1.identifier, + commitments: clientRound1.commitments, + }, + }; + const round2Result = await runSignEd25519Round2( + pool, + TEMP_ENC_SECRET, + round2Request, + ); + expect(round2Result.success).toBe(true); + + // Second Round 2 call with same session - should fail + const duplicateRound2Result = await runSignEd25519Round2( + pool, + TEMP_ENC_SECRET, + round2Request, + ); + + expect(duplicateRound2Result.success).toBe(false); + if (!duplicateRound2Result.success) { + expect(duplicateRound2Result.code).toBe("INVALID_TSS_SESSION"); + } + }); + + it("should fail when using COMPLETED session for Round2", async () => { + const { walletId, customerId, clientKeygenOutput } = + await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message for signing"); + + // Complete full signing flow first + const round1Res = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, { + email: TEST_EMAIL, + wallet_id: walletId, + customer_id: customerId, + msg: [...testMessage], + }); + expect(round1Res.success).toBe(true); + if (!round1Res.success) throw new Error("Round 1 failed"); + + const clientR1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + const allCommitments = [ + { identifier: clientR1.identifier, commitments: clientR1.commitments }, + { + identifier: round1Res.data.commitments_0.identifier, + commitments: round1Res.data.commitments_0.commitments, + }, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + const round2Res = await runSignEd25519Round2(pool, TEMP_ENC_SECRET, { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: round1Res.data.session_id, + commitments_1: { + identifier: clientR1.identifier, + commitments: clientR1.commitments, + }, + }); + expect(round2Res.success).toBe(true); + if (!round2Res.success) throw new Error("Round 2 failed"); + + const clientR2 = clientRunSignRound2Ed25519( + testMessage, + new Uint8Array(clientKeygenOutput.key_package), + new Uint8Array(clientR1.nonces), + allCommitments, + ); + + const allShares = [ + { + identifier: clientR2.identifier, + signature_share: clientR2.signature_share, + }, + { + identifier: round2Res.data.signature_share_0.identifier, + signature_share: round2Res.data.signature_share_0.signature_share, + }, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Extract user's verifying_share for aggregate + const userKeyPackageShares = extractKeyPackageSharesEd25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + // Complete the signing with Aggregate + const aggRes = await runSignEd25519Aggregate(pool, TEMP_ENC_SECRET, { + email: TEST_EMAIL, + wallet_id: walletId, + msg: [...testMessage], + all_commitments: allCommitments, + all_signature_shares: allShares, + user_verifying_share: userKeyPackageShares.verifying_share, + }); + expect(aggRes.success).toBe(true); + + // Now try to use the COMPLETED session for Round2 - should fail + const newClientR1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + const replayRound2Res = await runSignEd25519Round2( + pool, + TEMP_ENC_SECRET, + { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: round1Res.data.session_id, // Reusing completed session + commitments_1: { + identifier: newClientR1.identifier, + commitments: newClientR1.commitments, + }, + }, + ); + + expect(replayRound2Res.success).toBe(false); + if (!replayRound2Res.success) { + expect(replayRound2Res.code).toBe("INVALID_TSS_SESSION"); + } + }); + }); + + describe("runSignEd25519Aggregate", () => { + it("should aggregate signatures and produce valid signature", async () => { + const { walletId, customerId, clientKeygenOutput, serverKeygenOutput } = + await setUpEd25519Wallet(pool); + const testMessage = new TextEncoder().encode("Test message for signing"); + + // Round 1: Both parties generate commitments + const round1Request: SignEd25519Round1Request = { + email: TEST_EMAIL, + wallet_id: walletId, + customer_id: customerId, + msg: [...testMessage], + }; + const serverRound1Result = await runSignEd25519Round1( + pool, + TEMP_ENC_SECRET, + round1Request, + ); + expect(serverRound1Result.success).toBe(true); + if (!serverRound1Result.success) throw new Error("Server Round 1 failed"); + + const clientRound1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + // Collect all commitments (sorted by identifier) + const allCommitments = [ + { + identifier: clientRound1.identifier, + commitments: clientRound1.commitments, + }, + { + identifier: serverRound1Result.data.commitments_0.identifier, + commitments: serverRound1Result.data.commitments_0.commitments, + }, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Round 2: Both parties generate signature shares + const round2Request: SignEd25519Round2Request = { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: serverRound1Result.data.session_id, + commitments_1: { + identifier: clientRound1.identifier, + commitments: clientRound1.commitments, + }, + }; + const serverRound2Result = await runSignEd25519Round2( + pool, + TEMP_ENC_SECRET, + round2Request, + ); + expect(serverRound2Result.success).toBe(true); + if (!serverRound2Result.success) throw new Error("Server Round 2 failed"); + + const clientRound2 = clientRunSignRound2Ed25519( + testMessage, + new Uint8Array(clientKeygenOutput.key_package), + new Uint8Array(clientRound1.nonces), + allCommitments, + ); + + // Collect all signature shares (sorted by identifier) + const allSignatureShares = [ + { + identifier: clientRound2.identifier, + signature_share: clientRound2.signature_share, + }, + { + identifier: serverRound2Result.data.signature_share_0.identifier, + signature_share: + serverRound2Result.data.signature_share_0.signature_share, + }, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Extract user's verifying_share for aggregate + const userKeyPackageShares = extractKeyPackageSharesEd25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + // Aggregate + const aggregateRequest: SignEd25519AggregateRequest = { + email: TEST_EMAIL, + wallet_id: walletId, + msg: [...testMessage], + all_commitments: allCommitments, + all_signature_shares: allSignatureShares, + user_verifying_share: userKeyPackageShares.verifying_share, + }; + const aggregateResult = await runSignEd25519Aggregate( + pool, + TEMP_ENC_SECRET, + aggregateRequest, + ); + + expect(aggregateResult.success).toBe(true); + if (aggregateResult.success) { + expect(aggregateResult.data.signature).toBeDefined(); + expect(aggregateResult.data.signature.length).toBe(64); + + // Verify the signature + const isValid = runVerifyEd25519( + testMessage, + new Uint8Array(aggregateResult.data.signature), + new Uint8Array(clientKeygenOutput.public_key_package), + ); + expect(isValid).toBe(true); + } + }); + + it("should fail with wrong wallet type", async () => { + // Create a secp256k1 wallet instead of ed25519 + await setUpKSNodes(pool); + await insertKeyShareNodeMeta(pool, { sss_threshold: SSS_THRESHOLD }); + + const createUserRes = await createUser(pool, TEST_EMAIL, "google"); + if (!createUserRes.success) throw new Error("Failed to create user"); + + const encryptedShare = await encryptDataAsync( + JSON.stringify({ private_share: "test", public_key: "test" }), + TEMP_ENC_SECRET, + ); + + const createWalletRes = await createWallet(pool, { + user_id: createUserRes.data.user_id, + curve_type: "secp256k1", + public_key: Buffer.from("03" + "00".repeat(32), "hex"), + enc_tss_share: Buffer.from(encryptedShare, "utf-8"), + sss_threshold: SSS_THRESHOLD, + status: "ACTIVE" as WalletStatus, + }); + if (!createWalletRes.success) throw new Error("Failed to create wallet"); + + const aggregateRequest: SignEd25519AggregateRequest = { + email: TEST_EMAIL, + wallet_id: createWalletRes.data.wallet_id, + msg: [1, 2, 3], + all_commitments: [], + all_signature_shares: [], + user_verifying_share: new Array(32).fill(0), // Dummy value for error test + }; + + const result = await runSignEd25519Aggregate( + pool, + TEMP_ENC_SECRET, + aggregateRequest, + ); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("INVALID_WALLET_TYPE"); + } + }); + + it("should fail with invalid wallet_id", async () => { + await setUpEd25519Wallet(pool); + + const aggregateRequest: SignEd25519AggregateRequest = { + email: TEST_EMAIL, + wallet_id: "00000000-0000-0000-0000-000000000000", + msg: [1, 2, 3], + all_commitments: [], + all_signature_shares: [], + user_verifying_share: new Array(32).fill(0), // Dummy value for error test + }; + + const result = await runSignEd25519Aggregate( + pool, + TEMP_ENC_SECRET, + aggregateRequest, + ); + + expect(result.success).toBe(false); + if (!result.success) { + expect(result.code).toBe("UNAUTHORIZED"); + } + }); + }); + + describe("Full signing flow", () => { + it("should complete full signing flow with valid signature verification", async () => { + const { walletId, customerId, clientKeygenOutput } = + await setUpEd25519Wallet(pool); + const messages = [ + "Hello, Solana!", + "Transaction data", + "Another message to sign", + ]; + + for (const msgStr of messages) { + const message = new TextEncoder().encode(msgStr); + + // Round 1 + const round1Res = await runSignEd25519Round1(pool, TEMP_ENC_SECRET, { + email: TEST_EMAIL, + wallet_id: walletId, + customer_id: customerId, + msg: [...message], + }); + expect(round1Res.success).toBe(true); + if (!round1Res.success) continue; + + const clientR1 = clientRunSignRound1Ed25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + const allCommitments = [ + { + identifier: clientR1.identifier, + commitments: clientR1.commitments, + }, + { + identifier: round1Res.data.commitments_0.identifier, + commitments: round1Res.data.commitments_0.commitments, + }, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Round 2 + const round2Res = await runSignEd25519Round2(pool, TEMP_ENC_SECRET, { + email: TEST_EMAIL, + wallet_id: walletId, + session_id: round1Res.data.session_id, + commitments_1: { + identifier: clientR1.identifier, + commitments: clientR1.commitments, + }, + }); + expect(round2Res.success).toBe(true); + if (!round2Res.success) continue; + + const clientR2 = clientRunSignRound2Ed25519( + message, + new Uint8Array(clientKeygenOutput.key_package), + new Uint8Array(clientR1.nonces), + allCommitments, + ); + + const allShares = [ + { + identifier: clientR2.identifier, + signature_share: clientR2.signature_share, + }, + { + identifier: round2Res.data.signature_share_0.identifier, + signature_share: round2Res.data.signature_share_0.signature_share, + }, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Extract user's verifying_share for aggregate + const userKeyPackageShares = extractKeyPackageSharesEd25519( + new Uint8Array(clientKeygenOutput.key_package), + ); + + // Aggregate + const aggRes = await runSignEd25519Aggregate(pool, TEMP_ENC_SECRET, { + email: TEST_EMAIL, + wallet_id: walletId, + msg: [...message], + all_commitments: allCommitments, + all_signature_shares: allShares, + user_verifying_share: userKeyPackageShares.verifying_share, + }); + expect(aggRes.success).toBe(true); + if (!aggRes.success) continue; + + // Verify + const isValid = runVerifyEd25519( + message, + new Uint8Array(aggRes.data.signature), + new Uint8Array(clientKeygenOutput.public_key_package), + ); + expect(isValid).toBe(true); + } + }); + }); +}); From 897edede4232dad9548cca2358b62bdde1fdf785 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 17:46:46 +0900 Subject: [PATCH 12/17] tss_api: refactor sign ed25519 --- backend/tss_api/src/api/sign_ed25519/index.ts | 167 ------------------ backend/tss_api/src/routes/sign_ed25519.ts | 40 ----- common/oko_types/src/tss/sign_ed25519.ts | 18 -- crypto/teddsa/api_lib/src/index.ts | 16 -- embed/oko_attached/src/crypto/sign_ed25519.ts | 147 +++++++-------- 5 files changed, 74 insertions(+), 314 deletions(-) diff --git a/backend/tss_api/src/api/sign_ed25519/index.ts b/backend/tss_api/src/api/sign_ed25519/index.ts index d25f286b8..f46df7f64 100644 --- a/backend/tss_api/src/api/sign_ed25519/index.ts +++ b/backend/tss_api/src/api/sign_ed25519/index.ts @@ -11,14 +11,10 @@ import type { SignEd25519AggregateRequest, SignEd25519AggregateResponse, SignEd25519StageData, - SignEd25519Request, - SignEd25519Response, - PresignEd25519StageData, } from "@oko-wallet/oko-types/tss"; import { TssStageType, SignEd25519StageStatus, - PresignEd25519StageStatus, TssSessionState, } from "@oko-wallet/oko-types/tss"; import type { OkoApiResponse } from "@oko-wallet/oko-types/api_response"; @@ -333,169 +329,6 @@ export async function runSignEd25519Round2( } } -// New presign-based sign function -export async function runSignEd25519( - db: Pool, - encryptionSecret: string, - request: SignEd25519Request, -): Promise> { - try { - const { email, wallet_id, session_id, msg, commitments_1 } = request; - - const validateWalletEmailRes = await validateWalletEmail( - db, - wallet_id, - email, - ); - if (validateWalletEmailRes.success === false) { - return { - success: false, - code: "UNAUTHORIZED", - msg: validateWalletEmailRes.err, - }; - } - const wallet = validateWalletEmailRes.data; - - if (wallet.curve_type !== "ed25519") { - return { - success: false, - code: "INVALID_WALLET_TYPE", - msg: `Wallet is not ed25519 type: ${wallet.curve_type}`, - }; - } - - // Get presign stage with session data - const getStageRes = await getTssStageWithSessionData( - db, - session_id, - TssStageType.PRESIGN_ED25519, - ); - if (getStageRes.success === false) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `Failed to get TSS stage: ${getStageRes.err}`, - }; - } - const stage = getStageRes.data; - - // Validate session - if (!validateTssSession(stage, wallet_id)) { - return { - success: false, - code: "INVALID_TSS_SESSION", - msg: "Invalid session state or wallet mismatch", - }; - } - - // Validate stage status (must be COMPLETED presign, not USED) - if (!validateTssStage(stage, PresignEd25519StageStatus.COMPLETED)) { - return { - success: false, - code: "INVALID_TSS_SESSION", - msg: "Presign not found or already used. Please call presign_ed25519 first.", - }; - } - - const stageData = stage.stage_data as PresignEd25519StageData; - const { nonces, identifier, commitments } = stageData; - - if (!nonces || !identifier || !commitments) { - return { - success: false, - code: "INVALID_TSS_SESSION", - msg: "Missing presign data in stage", - }; - } - - const encryptedShare = wallet.enc_tss_share.toString("utf-8"); - const decryptedShare = await decryptDataAsync( - encryptedShare, - encryptionSecret, - ); - const storedShares = JSON.parse(decryptedShare) as { - signing_share: number[]; - verifying_share: number[]; - }; - - // Reconstruct key_package from stored shares - const serverIdentifier = participantToIdentifier(Participant.P1); - const verifyingKey = Array.from(wallet.public_key); - const minSigners = 2; - - let keyPackageBytes: Uint8Array; - try { - keyPackageBytes = reconstructKeyPackageEd25519( - new Uint8Array(storedShares.signing_share), - new Uint8Array(storedShares.verifying_share), - new Uint8Array(serverIdentifier), - new Uint8Array(verifyingKey), - minSigners, - ); - } catch (error) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `Failed to reconstruct key_package: ${error instanceof Error ? error.message : String(error)}`, - }; - } - - const serverCommitment = { - identifier, - commitments, - }; - - const allCommitments = [serverCommitment, commitments_1]; - allCommitments.sort((a, b) => { - const idA = a.identifier[0] ?? 0; - const idB = b.identifier[0] ?? 0; - return idA - idB; - }); - - const round2Result = runSignRound2Ed25519( - new Uint8Array(msg), - keyPackageBytes, - new Uint8Array(nonces), - allCommitments, - ); - - // Mark presign as USED and complete the session - const updateRes = await updateTssStageWithSessionState( - db, - stage.stage_id, - session_id, - { - stage_status: PresignEd25519StageStatus.USED, - stage_data: stageData, - }, - TssSessionState.COMPLETED, - ); - if (!updateRes.success) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `Failed to update TSS stage: ${updateRes.err}`, - }; - } - - return { - success: true, - data: { - signature_share_0: { - identifier: round2Result.identifier, - signature_share: round2Result.signature_share, - }, - }, - }; - } catch (error) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `runSignEd25519 error: ${error instanceof Error ? error.message : String(error)}`, - }; - } -} - export async function runSignEd25519Aggregate( db: Pool, encryptionSecret: string, diff --git a/backend/tss_api/src/routes/sign_ed25519.ts b/backend/tss_api/src/routes/sign_ed25519.ts index 904c21a1e..d24264eb1 100644 --- a/backend/tss_api/src/routes/sign_ed25519.ts +++ b/backend/tss_api/src/routes/sign_ed25519.ts @@ -6,8 +6,6 @@ import type { SignEd25519Round2Response, SignEd25519AggregateBody, SignEd25519AggregateResponse, - SignEd25519Body, - SignEd25519Response, } from "@oko-wallet/oko-types/tss"; import type { OkoApiResponse } from "@oko-wallet/oko-types/api_response"; import { ErrorCodeMap } from "@oko-wallet/oko-api-error-codes"; @@ -21,7 +19,6 @@ import { runSignEd25519Round1, runSignEd25519Round2, runSignEd25519Aggregate, - runSignEd25519, } from "@oko-wallet-tss-api/api/sign_ed25519"; import { type UserAuthenticatedRequest, @@ -315,43 +312,6 @@ export function setSignEd25519Routes(router: Router) { }, }); - router.post( - "/sign_ed25519", - [userJwtMiddleware, tssActivateMiddleware], - async ( - req: UserAuthenticatedRequest, - res: Response>, - ) => { - const state = req.app.locals as any; - const user = res.locals.user; - const body = req.body; - - if (!user.wallet_id_ed25519) { - res.status(400).json({ - success: false, - code: "WALLET_NOT_FOUND", - msg: "Ed25519 wallet not found. Please create one first.", - }); - return; - } - - const result = await runSignEd25519(state.db, state.encryption_secret, { - email: user.email.toLowerCase(), - wallet_id: user.wallet_id_ed25519, - session_id: body.session_id, - msg: body.msg, - commitments_1: body.commitments_1, - }); - - if (result.success === false) { - res.status(ErrorCodeMap[result.code] ?? 500).json(result); - return; - } - - sendResponseWithNewToken(res, result.data); - }, - ); - registry.registerPath({ method: "post", path: "/tss/v1/sign_ed25519/aggregate", diff --git a/common/oko_types/src/tss/sign_ed25519.ts b/common/oko_types/src/tss/sign_ed25519.ts index fdc6be486..96d4ab2c7 100644 --- a/common/oko_types/src/tss/sign_ed25519.ts +++ b/common/oko_types/src/tss/sign_ed25519.ts @@ -72,21 +72,3 @@ export interface PresignEd25519Response { } export type PresignEd25519Body = Record; - -export interface SignEd25519Request { - email: string; - wallet_id: string; - session_id: string; - msg: number[]; - commitments_1: CommitmentEntry; -} - -export interface SignEd25519Response { - signature_share_0: SignatureShareEntry; -} - -export type SignEd25519Body = { - session_id: string; - msg: number[]; - commitments_1: CommitmentEntry; -}; diff --git a/crypto/teddsa/api_lib/src/index.ts b/crypto/teddsa/api_lib/src/index.ts index f608e1ed8..db81f64b6 100644 --- a/crypto/teddsa/api_lib/src/index.ts +++ b/crypto/teddsa/api_lib/src/index.ts @@ -8,8 +8,6 @@ import type { SignEd25519AggregateResponse, PresignEd25519Body, PresignEd25519Response, - SignEd25519Body, - SignEd25519Response, } from "@oko-wallet/oko-types/tss"; import type { SignInResponse } from "@oko-wallet/oko-types/user"; import type { @@ -194,17 +192,3 @@ export async function reqPresignEd25519( ); return resp; } - -export async function reqSignEd25519( - endpoint: string, - payload: SignEd25519Body, - authToken: string, -) { - const resp: OkoApiResponse = await makePostRequest( - endpoint, - "sign_ed25519", - payload, - authToken, - ); - return resp; -} diff --git a/embed/oko_attached/src/crypto/sign_ed25519.ts b/embed/oko_attached/src/crypto/sign_ed25519.ts index 486991b65..8afa3a9d6 100644 --- a/embed/oko_attached/src/crypto/sign_ed25519.ts +++ b/embed/oko_attached/src/crypto/sign_ed25519.ts @@ -11,7 +11,7 @@ import type { } from "@oko-wallet/teddsa-interface"; import type { Result } from "@oko-wallet/stdlib-js"; import type { MakeSignOutputError } from "@oko-wallet/oko-sdk-core"; -import { reqPresignEd25519, reqSignEd25519 } from "@oko-wallet/teddsa-api-lib"; +import { reqPresignEd25519 } from "@oko-wallet/teddsa-api-lib"; import { TSS_V1_ENDPOINT } from "@oko-wallet-attached/requests/oko_api"; @@ -82,78 +82,79 @@ export async function makeSignOutputEd25519( return { success: false, err: { type: "aborted" } }; } - const serverSignRes = await reqSignEd25519( - TSS_V1_ENDPOINT, - { - session_id: sessionId, - msg: [...message], - commitments_1: clientCommitment, - }, - authToken, - ); - - if (!serverSignRes.success) { - return { - success: false, - err: { - type: "sign_fail", - error: { type: "error", msg: serverSignRes.msg }, - }, - }; - } - - const serverSignatureShare: SignatureShareEntry = - serverSignRes.data.signature_share_0; - - if (getIsAborted()) { - return { success: false, err: { type: "aborted" } }; - } - - const round2Result = teddsaSignRound2( - message, - keyPackage.keyPackage, - new Uint8Array(round1Result.data.nonces), - allCommitments, - ); - - if (!round2Result.success) { - return { - success: false, - err: { - type: "sign_fail", - error: { type: "error", msg: round2Result.err }, - }, - }; - } - - const clientSignatureShare: SignatureShareEntry = { - identifier: round2Result.data.identifier, - signature_share: round2Result.data.signature_share, - }; - - const allSignatureShares: SignatureShareEntry[] = [ - clientSignatureShare, - serverSignatureShare, - ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); - - const aggregateResult = teddsaAggregate( - message, - allCommitments, - allSignatureShares, - keyPackage.publicKeyPackage, - ); - - if (!aggregateResult.success) { - return { - success: false, - err: { - type: "sign_fail", - error: { type: "error", msg: aggregateResult.err }, - }, - }; - } - - return { success: true, data: aggregateResult.data }; + // @TODO + // const serverSignRes = await reqSignEd25519( + // TSS_V1_ENDPOINT, + // { + // session_id: sessionId, + // msg: [...message], + // commitments_1: clientCommitment, + // }, + // authToken, + // ); + + // if (!serverSignRes.success) { + // return { + // success: false, + // err: { + // type: "sign_fail", + // error: { type: "error", msg: serverSignRes.msg }, + // }, + // }; + // } + + // const serverSignatureShare: SignatureShareEntry = + // serverSignRes.data.signature_share_0; + + // if (getIsAborted()) { + // return { success: false, err: { type: "aborted" } }; + // } + + // const round2Result = teddsaSignRound2( + // message, + // keyPackage.keyPackage, + // new Uint8Array(round1Result.data.nonces), + // allCommitments, + // ); + + // if (!round2Result.success) { + // return { + // success: false, + // err: { + // type: "sign_fail", + // error: { type: "error", msg: round2Result.err }, + // }, + // }; + // } + + // const clientSignatureShare: SignatureShareEntry = { + // identifier: round2Result.data.identifier, + // signature_share: round2Result.data.signature_share, + // }; + + // const allSignatureShares: SignatureShareEntry[] = [ + // clientSignatureShare, + // serverSignatureShare, + // ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // const aggregateResult = teddsaAggregate( + // message, + // allCommitments, + // allSignatureShares, + // keyPackage.publicKeyPackage, + // ); + + // if (!aggregateResult.success) { + // return { + // success: false, + // err: { + // type: "sign_fail", + // error: { type: "error", msg: aggregateResult.err }, + // }, + // }; + // } + + return { success: true, data: new Uint8Array(64) }; } catch (error) { return { success: false, From 9c65c3cd06fd865c0de074f96a960ea653c68cfe Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 18:07:30 +0900 Subject: [PATCH 13/17] tss_api: remove presign ed25519 --- .../src/api/presign_ed25519/index.test.ts | 368 ------------------ .../tss_api/src/api/presign_ed25519/index.ts | 145 ------- backend/tss_api/src/routes/index.ts | 2 - backend/tss_api/src/routes/presign_ed25519.ts | 129 ------ common/oko_types/src/tss/sign_ed25519.ts | 13 - common/oko_types/src/tss/tss_stage.ts | 10 +- crypto/teddsa/api_lib/src/index.ts | 18 - embed/oko_attached/src/crypto/sign_ed25519.ts | 102 ++--- 8 files changed, 52 insertions(+), 735 deletions(-) delete mode 100644 backend/tss_api/src/api/presign_ed25519/index.test.ts delete mode 100644 backend/tss_api/src/api/presign_ed25519/index.ts delete mode 100644 backend/tss_api/src/routes/presign_ed25519.ts diff --git a/backend/tss_api/src/api/presign_ed25519/index.test.ts b/backend/tss_api/src/api/presign_ed25519/index.test.ts deleted file mode 100644 index cbc01da0a..000000000 --- a/backend/tss_api/src/api/presign_ed25519/index.test.ts +++ /dev/null @@ -1,368 +0,0 @@ -import { Pool } from "pg"; -import type { PresignEd25519Request } from "@oko-wallet/oko-types/tss"; -import { Participant } from "@oko-wallet/teddsa-interface"; -import { runKeygenCentralizedEd25519 } from "@oko-wallet/teddsa-addon/src/server"; -import { createPgConn } from "@oko-wallet/postgres-lib"; -import { insertKSNode } from "@oko-wallet/oko-pg-interface/ks_nodes"; -import { createUser } from "@oko-wallet/oko-pg-interface/oko_users"; -import { - createWallet, - getWalletById, -} from "@oko-wallet/oko-pg-interface/oko_wallets"; -import { insertKeyShareNodeMeta } from "@oko-wallet/oko-pg-interface/key_share_node_meta"; -import { insertCustomer } from "@oko-wallet/oko-pg-interface/customers"; -import type { WalletStatus } from "@oko-wallet/oko-types/wallets"; -import { - TssStageType, - PresignEd25519StageStatus, -} from "@oko-wallet/oko-types/tss"; -import { getTssStageWithSessionData } from "@oko-wallet/oko-pg-interface/tss"; - -import { resetPgDatabase } from "@oko-wallet-tss-api/testing/database"; -import { testPgConfig } from "@oko-wallet-tss-api/database/test_config"; -import { runKeygenEd25519 } from "@oko-wallet-tss-api/api/keygen_ed25519"; -import { runPresignEd25519 } from "@oko-wallet-tss-api/api/presign_ed25519"; -import { TEMP_ENC_SECRET } from "@oko-wallet-tss-api/api/utils"; -import { TEST_CUSTOMER } from "@oko-wallet-tss-api/api/tests"; - -const SSS_THRESHOLD = 2; -const TEST_EMAIL = "presign-ed25519-test@test.com"; -const TEST_JWT_CONFIG = { - secret: "test-jwt-secret-for-presign-ed25519", - expires_in: "1h", -}; - -async function setUpKSNodes(pool: Pool): Promise { - const ksNodeNames = ["ksNode1", "ksNode2"]; - const ksNodeIds = []; - const createKSNodesRes = await Promise.all( - ksNodeNames.map((ksNodeName) => - insertKSNode(pool, ksNodeName, `http://test.com/${ksNodeName}`), - ), - ); - for (const res of createKSNodesRes) { - if (res.success === false) { - throw new Error("Failed to create ks nodes"); - } - ksNodeIds.push(res.data.node_id); - } - return ksNodeIds; -} - -async function setUpKeyShareNodeMeta(pool: Pool): Promise { - await insertKeyShareNodeMeta(pool, { - sss_threshold: SSS_THRESHOLD, - }); -} - -async function setUpEd25519Wallet( - pool: Pool, - email: string = TEST_EMAIL, -): Promise<{ walletId: string; customerId: string }> { - // Create customer - const insertCustomerRes = await insertCustomer(pool, TEST_CUSTOMER); - if (insertCustomerRes.success === false) { - throw new Error(`Failed to create customer: ${insertCustomerRes.err}`); - } - - // Set up KS nodes and metadata - await setUpKSNodes(pool); - await setUpKeyShareNodeMeta(pool); - - // Create wallet using keygen - const keygenResult = runKeygenCentralizedEd25519(); - const serverKeygenOutput = keygenResult.keygen_outputs[Participant.P1]; - - const keygenRequest = { - auth_type: "google" as const, - user_identifier: email, - keygen_2: { - ...serverKeygenOutput, - public_key: [...keygenResult.public_key], - }, - email: email, - }; - - const keygenResult_res = await runKeygenEd25519( - pool, - TEST_JWT_CONFIG, - keygenRequest, - TEMP_ENC_SECRET, - ); - - if (!keygenResult_res.success) { - throw new Error(`Failed to create wallet: ${keygenResult_res.msg}`); - } - - return { - walletId: keygenResult_res.data.user.wallet_id, - customerId: TEST_CUSTOMER.customer_id, - }; -} - -function generatePresignRequest( - email: string, - walletId: string, - customerId: string, -): PresignEd25519Request { - return { - email, - wallet_id: walletId, - customer_id: customerId, - }; -} - -describe("Ed25519 Presign", () => { - let pool: Pool; - - beforeAll(async () => { - const config = testPgConfig; - const createPostgresRes = await createPgConn({ - database: config.database, - host: config.host, - password: config.password, - user: config.user, - port: config.port, - ssl: config.ssl, - }); - - if (createPostgresRes.success === false) { - console.error(createPostgresRes.err); - throw new Error("Failed to create postgres database"); - } - - pool = createPostgresRes.data; - }); - - afterAll(async () => { - await pool.end(); - }); - - beforeEach(async () => { - await resetPgDatabase(pool); - }); - - describe("runPresignEd25519", () => { - it("should successfully generate presign and create session", async () => { - const { walletId, customerId } = await setUpEd25519Wallet(pool); - - const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); - - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - if (!result.success) { - console.error("Presign failed:", { - code: result.code, - msg: result.msg, - }); - } - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.session_id).toBeDefined(); - expect(result.data.commitments_0).toBeDefined(); - expect(result.data.commitments_0.identifier).toBeDefined(); - expect(result.data.commitments_0.commitments).toBeDefined(); - expect(result.data.commitments_0.identifier.length).toBe(32); - expect(result.data.commitments_0.commitments.length).toBeGreaterThan(0); - } - }); - - it("should create TSS session and stage in database", async () => { - const { walletId, customerId } = await setUpEd25519Wallet(pool); - - const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); - - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - expect(result.success).toBe(true); - if (result.success) { - const sessionId = result.data.session_id; - - // Verify TSS session was created - const sessionQuery = await pool.query( - "SELECT session_id, wallet_id, customer_id FROM tss_sessions WHERE session_id = $1", - [sessionId], - ); - expect(sessionQuery.rows).toHaveLength(1); - expect(sessionQuery.rows[0].wallet_id).toBe(walletId); - expect(sessionQuery.rows[0].customer_id).toBe(customerId); - - // Verify TSS stage was created - const getStageRes = await getTssStageWithSessionData( - pool, - sessionId, - TssStageType.PRESIGN_ED25519, - ); - expect(getStageRes.success).toBe(true); - if (getStageRes.success && getStageRes.data) { - const stage = getStageRes.data; - expect(stage.session_id).toBe(sessionId); - expect(stage.stage_type).toBe(TssStageType.PRESIGN_ED25519); - expect(stage.stage_status).toBe(PresignEd25519StageStatus.COMPLETED); - expect(stage.stage_data).toBeDefined(); - - const stageData = stage.stage_data as { - nonces: number[]; - identifier: number[]; - commitments: number[]; - }; - expect(stageData.nonces).toBeDefined(); - expect(stageData.identifier).toBeDefined(); - expect(stageData.commitments).toBeDefined(); - expect(stageData.identifier.length).toBe(32); - } - } - }); - - it("should return valid commitments structure", async () => { - const { walletId, customerId } = await setUpEd25519Wallet(pool); - - const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); - - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - expect(result.success).toBe(true); - if (result.success) { - const commitments = result.data.commitments_0; - - // Verify commitments structure - expect(commitments).toBeDefined(); - expect(commitments.identifier).toBeDefined(); - expect(Array.isArray(commitments.identifier)).toBe(true); - expect(commitments.identifier.length).toBe(32); - - expect(commitments.commitments).toBeDefined(); - expect(Array.isArray(commitments.commitments)).toBe(true); - expect(commitments.commitments.length).toBeGreaterThan(0); - } - }); - - it("should fail with UNAUTHORIZED for invalid email", async () => { - const { walletId, customerId } = await setUpEd25519Wallet(pool); - - const request = generatePresignRequest( - "wrong-email@test.com", - walletId, - customerId, - ); - - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - expect(result.success).toBe(false); - if (!result.success) { - expect(result.code).toBe("UNAUTHORIZED"); - } - }); - - it("should fail with UNAUTHORIZED for invalid wallet_id", async () => { - const { customerId } = await setUpEd25519Wallet(pool); - - const request = generatePresignRequest( - TEST_EMAIL, - "invalid-wallet-id", - customerId, - ); - - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - expect(result.success).toBe(false); - if (!result.success) { - expect(result.code).toBe("UNAUTHORIZED"); - } - }); - - it("should fail with INVALID_WALLET_TYPE for non-ed25519 wallet", async () => { - // Create user and secp256k1 wallet - const createUserRes = await createUser(pool, TEST_EMAIL, "google"); - expect(createUserRes.success).toBe(true); - if (!createUserRes.success) { - throw new Error("Failed to create user"); - } - - const userId = createUserRes.data.user_id; - - // Create secp256k1 wallet - const createWalletRes = await createWallet(pool, { - user_id: userId, - curve_type: "secp256k1", - public_key: Buffer.from("03" + "00".repeat(32), "hex"), - enc_tss_share: Buffer.from("encrypted-share", "utf-8"), - sss_threshold: SSS_THRESHOLD, - status: "ACTIVE" as WalletStatus, - }); - expect(createWalletRes.success).toBe(true); - if (!createWalletRes.success) { - throw new Error("Failed to create wallet"); - } - - const walletId = createWalletRes.data.wallet_id; - const insertCustomerRes = await insertCustomer(pool, TEST_CUSTOMER); - if (insertCustomerRes.success === false) { - throw new Error("Failed to create customer"); - } - - const request = generatePresignRequest( - TEST_EMAIL, - walletId, - TEST_CUSTOMER.customer_id, - ); - - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - expect(result.success).toBe(false); - if (!result.success) { - expect(result.code).toBe("INVALID_WALLET_TYPE"); - expect(result.msg).toContain("not ed25519 type"); - } - }); - - it("should handle multiple presigns for same wallet", async () => { - const { walletId, customerId } = await setUpEd25519Wallet(pool); - - // Generate first presign - const request1 = generatePresignRequest(TEST_EMAIL, walletId, customerId); - const result1 = await runPresignEd25519(pool, TEMP_ENC_SECRET, request1); - - expect(result1.success).toBe(true); - - // Generate second presign - const request2 = generatePresignRequest(TEST_EMAIL, walletId, customerId); - const result2 = await runPresignEd25519(pool, TEMP_ENC_SECRET, request2); - - expect(result2.success).toBe(true); - if (result1.success && result2.success) { - // Should create different sessions - expect(result1.data.session_id).not.toBe(result2.data.session_id); - - // Both should have valid commitments - expect(result1.data.commitments_0).toBeDefined(); - expect(result2.data.commitments_0).toBeDefined(); - } - }); - - it("should reconstruct key_package from stored shares correctly", async () => { - const { walletId, customerId } = await setUpEd25519Wallet(pool); - - // Get wallet to verify shares are stored correctly - const getWalletRes = await getWalletById(pool, walletId); - expect(getWalletRes.success).toBe(true); - if (!getWalletRes.success || !getWalletRes.data) { - throw new Error("Failed to get wallet"); - } - - const wallet = getWalletRes.data; - expect(wallet.curve_type).toBe("ed25519"); - - // Presign should succeed using reconstructed key_package - const request = generatePresignRequest(TEST_EMAIL, walletId, customerId); - const result = await runPresignEd25519(pool, TEMP_ENC_SECRET, request); - - expect(result.success).toBe(true); - if (result.success) { - // If key_package reconstruction failed, we would get an error - // So success means reconstruction worked - expect(result.data.session_id).toBeDefined(); - } - }); - }); -}); diff --git a/backend/tss_api/src/api/presign_ed25519/index.ts b/backend/tss_api/src/api/presign_ed25519/index.ts deleted file mode 100644 index cc656a93d..000000000 --- a/backend/tss_api/src/api/presign_ed25519/index.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { - createTssSession, - createTssStage, -} from "@oko-wallet/oko-pg-interface/tss"; -import type { - PresignEd25519Request, - PresignEd25519Response, - PresignEd25519StageData, -} from "@oko-wallet/oko-types/tss"; -import { - TssStageType, - PresignEd25519StageStatus, -} from "@oko-wallet/oko-types/tss"; -import type { OkoApiResponse } from "@oko-wallet/oko-types/api_response"; -import { Pool } from "pg"; -import { decryptDataAsync } from "@oko-wallet/crypto-js/node"; -import { - runSignRound1Ed25519, - reconstructKeyPackageEd25519, -} from "@oko-wallet/teddsa-addon/src/server"; -import { - Participant, - participantToIdentifier, -} from "@oko-wallet/teddsa-interface"; - -import { validateWalletEmail } from "@oko-wallet-tss-api/api/utils"; - -export async function runPresignEd25519( - db: Pool, - encryptionSecret: string, - request: PresignEd25519Request, -): Promise> { - try { - const { email, wallet_id, customer_id } = request; - - const validateWalletEmailRes = await validateWalletEmail( - db, - wallet_id, - email, - ); - if (validateWalletEmailRes.success === false) { - return { - success: false, - code: "UNAUTHORIZED", - msg: validateWalletEmailRes.err, - }; - } - const wallet = validateWalletEmailRes.data; - - if (wallet.curve_type !== "ed25519") { - return { - success: false, - code: "INVALID_WALLET_TYPE", - msg: `Wallet is not ed25519 type: ${wallet.curve_type}`, - }; - } - - const encryptedShare = wallet.enc_tss_share.toString("utf-8"); - const decryptedShare = await decryptDataAsync( - encryptedShare, - encryptionSecret, - ); - const storedShares = JSON.parse(decryptedShare) as { - signing_share: number[]; - verifying_share: number[]; - }; - - // Reconstruct key_package from stored shares - const serverIdentifier = participantToIdentifier(Participant.P1); - const verifyingKey = Array.from(wallet.public_key); - const minSigners = 2; - - let keyPackageBytes: Uint8Array; - try { - keyPackageBytes = reconstructKeyPackageEd25519( - new Uint8Array(storedShares.signing_share), - new Uint8Array(storedShares.verifying_share), - new Uint8Array(serverIdentifier), - new Uint8Array(verifyingKey), - minSigners, - ); - } catch (error) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `Failed to reconstruct key_package: ${error instanceof Error ? error.message : String(error)}`, - }; - } - - // Generate nonces and commitments (Round 1 without message) - const round1Result = runSignRound1Ed25519(keyPackageBytes); - - // Create TSS session - const sessionRes = await createTssSession(db, { - customer_id, - wallet_id, - }); - if (!sessionRes.success) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `Failed to create TSS session: ${sessionRes.err}`, - }; - } - const session = sessionRes.data; - - // Create TSS stage with presign data (nonces stored for later use) - const stageData: PresignEd25519StageData = { - nonces: round1Result.nonces, - identifier: round1Result.identifier, - commitments: round1Result.commitments, - }; - - const stageRes = await createTssStage(db, { - session_id: session.session_id, - stage_type: TssStageType.PRESIGN_ED25519, - stage_status: PresignEd25519StageStatus.COMPLETED, - stage_data: stageData, - }); - if (!stageRes.success) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `Failed to create TSS stage: ${stageRes.err}`, - }; - } - - return { - success: true, - data: { - session_id: session.session_id, - commitments_0: { - identifier: round1Result.identifier, - commitments: round1Result.commitments, - }, - }, - }; - } catch (error) { - return { - success: false, - code: "UNKNOWN_ERROR", - msg: `runPresignEd25519 error: ${error instanceof Error ? error.message : String(error)}`, - }; - } -} diff --git a/backend/tss_api/src/routes/index.ts b/backend/tss_api/src/routes/index.ts index 183639b6a..4894fa75d 100644 --- a/backend/tss_api/src/routes/index.ts +++ b/backend/tss_api/src/routes/index.ts @@ -4,7 +4,6 @@ import { setKeygenRoutes } from "./keygen"; import { setKeygenEd25519Routes } from "./keygen_ed25519"; import { setTriplesRoutes } from "./triples"; import { setPresignRoutes } from "./presign"; -import { setPresignEd25519Routes } from "./presign_ed25519"; import { setSignRoutes } from "./sign"; import { setSignEd25519Routes } from "./sign_ed25519"; import { setWalletEd25519Routes } from "./wallet_ed25519"; @@ -19,7 +18,6 @@ export function makeTssRouter() { setKeygenEd25519Routes(router); setTriplesRoutes(router); setPresignRoutes(router); - setPresignEd25519Routes(router); setSignRoutes(router); setSignEd25519Routes(router); setWalletEd25519Routes(router); diff --git a/backend/tss_api/src/routes/presign_ed25519.ts b/backend/tss_api/src/routes/presign_ed25519.ts deleted file mode 100644 index 08efca0a0..000000000 --- a/backend/tss_api/src/routes/presign_ed25519.ts +++ /dev/null @@ -1,129 +0,0 @@ -import type { Response, Router } from "express"; -import type { - PresignEd25519Body, - PresignEd25519Response, -} from "@oko-wallet/oko-types/tss"; -import type { OkoApiResponse } from "@oko-wallet/oko-types/api_response"; -import { ErrorCodeMap } from "@oko-wallet/oko-api-error-codes"; -import { - ErrorResponseSchema, - UserAuthHeaderSchema, -} from "@oko-wallet/oko-api-openapi/common"; -import { registry } from "@oko-wallet/oko-api-openapi"; - -import { runPresignEd25519 } from "@oko-wallet-tss-api/api/presign_ed25519"; -import { - type UserAuthenticatedRequest, - userJwtMiddleware, - sendResponseWithNewToken, -} from "@oko-wallet-tss-api/middleware/keplr_auth"; -import { apiKeyMiddleware } from "@oko-wallet-tss-api/middleware/api_key_auth"; -import { tssActivateMiddleware } from "@oko-wallet-tss-api/middleware/tss_activate"; - -export function setPresignEd25519Routes(router: Router) { - registry.registerPath({ - method: "post", - path: "/tss/v1/presign_ed25519", - tags: ["TSS"], - summary: "Generate Ed25519 presign (nonces and commitments)", - description: - "Pre-generate nonces and commitments for Ed25519 threshold signing. " + - "This can be called before knowing the message to sign.", - security: [{ userAuth: [] }], - request: { - headers: UserAuthHeaderSchema, - body: { - required: false, - content: { - "application/json": { - schema: { - type: "object", - properties: {}, - }, - }, - }, - }, - }, - responses: { - 200: { - description: "Successfully generated presign", - content: { - "application/json": { - schema: { - type: "object", - properties: { - success: { type: "boolean" }, - data: { - type: "object", - properties: { - session_id: { type: "string" }, - commitments_0: { - type: "object", - properties: { - identifier: { - type: "array", - items: { type: "number" }, - }, - commitments: { - type: "array", - items: { type: "number" }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - 401: { - description: "Unauthorized", - content: { "application/json": { schema: ErrorResponseSchema } }, - }, - 500: { - description: "Internal server error", - content: { "application/json": { schema: ErrorResponseSchema } }, - }, - }, - }); - - router.post( - "/presign_ed25519", - [apiKeyMiddleware, userJwtMiddleware, tssActivateMiddleware], - async ( - req: UserAuthenticatedRequest, - res: Response>, - ) => { - const state = req.app.locals as any; - const user = res.locals.user; - const apiKey = res.locals.api_key; - - if (!user.wallet_id_ed25519) { - res.status(400).json({ - success: false, - code: "WALLET_NOT_FOUND", - msg: "Ed25519 wallet not found. Please create one first.", - }); - return; - } - - const result = await runPresignEd25519( - state.db, - state.encryption_secret, - { - email: user.email.toLowerCase(), - wallet_id: user.wallet_id_ed25519, - customer_id: apiKey.customer_id, - }, - ); - - if (result.success === false) { - res.status(ErrorCodeMap[result.code] ?? 500).json(result); - return; - } - - sendResponseWithNewToken(res, result.data); - }, - ); -} diff --git a/common/oko_types/src/tss/sign_ed25519.ts b/common/oko_types/src/tss/sign_ed25519.ts index 96d4ab2c7..5188c817a 100644 --- a/common/oko_types/src/tss/sign_ed25519.ts +++ b/common/oko_types/src/tss/sign_ed25519.ts @@ -59,16 +59,3 @@ export interface SignEd25519ServerState { nonces: number[]; identifier: number[]; } - -export interface PresignEd25519Request { - email: string; - wallet_id: string; - customer_id: string; -} - -export interface PresignEd25519Response { - session_id: string; - commitments_0: CommitmentEntry; -} - -export type PresignEd25519Body = Record; diff --git a/common/oko_types/src/tss/tss_stage.ts b/common/oko_types/src/tss/tss_stage.ts index 65d129caa..7af8688ef 100644 --- a/common/oko_types/src/tss/tss_stage.ts +++ b/common/oko_types/src/tss/tss_stage.ts @@ -18,7 +18,6 @@ export enum TssStageType { PRESIGN = "PRESIGN", SIGN = "SIGN", SIGN_ED25519 = "SIGN_ED25519", - PRESIGN_ED25519 = "PRESIGN_ED25519", } interface TssStageBase { @@ -132,12 +131,6 @@ export type SignEd25519Stage = TssStageBase & { stage_data: SignEd25519StageData; }; -export type PresignEd25519Stage = TssStageBase & { - stage_type: TssStageType.PRESIGN_ED25519; - stage_status: PresignEd25519StageStatus; - stage_data: PresignEd25519StageData; -}; - export type TssStageStatus = | TriplesStageStatus | PresignStageStatus @@ -149,8 +142,7 @@ export type TssStage = | TriplesStage | PresignStage | SignStage - | SignEd25519Stage - | PresignEd25519Stage; + | SignEd25519Stage; export type CreateTssStageRequest = Pick< TssStage, diff --git a/crypto/teddsa/api_lib/src/index.ts b/crypto/teddsa/api_lib/src/index.ts index db81f64b6..78aa4f2c3 100644 --- a/crypto/teddsa/api_lib/src/index.ts +++ b/crypto/teddsa/api_lib/src/index.ts @@ -6,8 +6,6 @@ import type { SignEd25519Round2Response, SignEd25519AggregateBody, SignEd25519AggregateResponse, - PresignEd25519Body, - PresignEd25519Response, } from "@oko-wallet/oko-types/tss"; import type { SignInResponse } from "@oko-wallet/oko-types/user"; import type { @@ -176,19 +174,3 @@ export async function reqSignEd25519Aggregate( ); return resp; } - -export async function reqPresignEd25519( - endpoint: string, - payload: PresignEd25519Body, - apiKey: string, - authToken: string, -) { - const resp: OkoApiResponse = await makePostRequest( - endpoint, - "presign_ed25519", - payload, - authToken, - apiKey, - ); - return resp; -} diff --git a/embed/oko_attached/src/crypto/sign_ed25519.ts b/embed/oko_attached/src/crypto/sign_ed25519.ts index 8afa3a9d6..be595f226 100644 --- a/embed/oko_attached/src/crypto/sign_ed25519.ts +++ b/embed/oko_attached/src/crypto/sign_ed25519.ts @@ -11,7 +11,6 @@ import type { } from "@oko-wallet/teddsa-interface"; import type { Result } from "@oko-wallet/stdlib-js"; import type { MakeSignOutputError } from "@oko-wallet/oko-sdk-core"; -import { reqPresignEd25519 } from "@oko-wallet/teddsa-api-lib"; import { TSS_V1_ENDPOINT } from "@oko-wallet-attached/requests/oko_api"; @@ -29,60 +28,61 @@ export async function makeSignOutputEd25519( getIsAborted: () => boolean, ): Promise> { try { - if (getIsAborted()) { - return { success: false, err: { type: "aborted" } }; - } - - const presignRes = await reqPresignEd25519( - TSS_V1_ENDPOINT, - {}, - apiKey, - authToken, - ); - - if (!presignRes.success) { - return { - success: false, - err: { - type: "sign_fail", - error: { type: "error", msg: presignRes.msg }, - }, - }; - } - - const { session_id: sessionId, commitments_0: serverCommitment } = - presignRes.data; - - if (getIsAborted()) { - return { success: false, err: { type: "aborted" } }; - } - - const round1Result = teddsaSignRound1(keyPackage.keyPackage); - if (!round1Result.success) { - return { - success: false, - err: { - type: "sign_fail", - error: { type: "error", msg: round1Result.err }, - }, - }; - } + // @TODO - const clientCommitment: CommitmentEntry = { - identifier: round1Result.data.identifier, - commitments: round1Result.data.commitments, - }; + // if (getIsAborted()) { + // return { success: false, err: { type: "aborted" } }; + // } + + // const presignRes = await reqPresignEd25519( + // TSS_V1_ENDPOINT, + // {}, + // apiKey, + // authToken, + // ); - const allCommitments: CommitmentEntry[] = [ - clientCommitment, - serverCommitment, - ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + // if (!presignRes.success) { + // return { + // success: false, + // err: { + // type: "sign_fail", + // error: { type: "error", msg: presignRes.msg }, + // }, + // }; + // } - if (getIsAborted()) { - return { success: false, err: { type: "aborted" } }; - } + // const { session_id: sessionId, commitments_0: serverCommitment } = + // presignRes.data; + + // if (getIsAborted()) { + // return { success: false, err: { type: "aborted" } }; + // } + + // const round1Result = teddsaSignRound1(keyPackage.keyPackage); + // if (!round1Result.success) { + // return { + // success: false, + // err: { + // type: "sign_fail", + // error: { type: "error", msg: round1Result.err }, + // }, + // }; + // } + + // const clientCommitment: CommitmentEntry = { + // identifier: round1Result.data.identifier, + // commitments: round1Result.data.commitments, + // }; + + // const allCommitments: CommitmentEntry[] = [ + // clientCommitment, + // serverCommitment, + // ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // if (getIsAborted()) { + // return { success: false, err: { type: "aborted" } }; + // } - // @TODO // const serverSignRes = await reqSignEd25519( // TSS_V1_ENDPOINT, // { From a6aa48721267d1e71a8fc5b95634dc3823304cdb Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 18:34:28 +0900 Subject: [PATCH 14/17] tss_api: refactor sign ed25519 stage --- .../src/api/sign_ed25519/index.test.ts | 130 +++++++++++++++++- backend/tss_api/src/api/sign_ed25519/index.ts | 62 ++++++++- backend/tss_api/src/routes/sign_ed25519.ts | 3 + common/oko_types/src/tss/sign_ed25519.ts | 2 + 4 files changed, 193 insertions(+), 4 deletions(-) diff --git a/backend/tss_api/src/api/sign_ed25519/index.test.ts b/backend/tss_api/src/api/sign_ed25519/index.test.ts index 14a143a1e..0f16d68cd 100644 --- a/backend/tss_api/src/api/sign_ed25519/index.test.ts +++ b/backend/tss_api/src/api/sign_ed25519/index.test.ts @@ -4,6 +4,12 @@ import type { SignEd25519Round2Request, SignEd25519AggregateRequest, } from "@oko-wallet/oko-types/tss"; +import { + TssStageType, + SignEd25519StageStatus, + TssSessionState, +} from "@oko-wallet/oko-types/tss"; +import { getTssStageWithSessionData } from "@oko-wallet/oko-pg-interface/tss"; import { Participant } from "@oko-wallet/teddsa-interface"; import { runKeygenCentralizedEd25519, @@ -186,6 +192,22 @@ describe("Ed25519 Signing", () => { expect(result.data.commitments_0.commitments).toBeDefined(); expect(Array.isArray(result.data.commitments_0.identifier)).toBe(true); expect(Array.isArray(result.data.commitments_0.commitments)).toBe(true); + + // Verify stage status is ROUND_1 + const getStageRes = await getTssStageWithSessionData( + pool, + result.data.session_id, + TssStageType.SIGN_ED25519, + ); + expect(getStageRes.success).toBe(true); + if (getStageRes.success && getStageRes.data) { + expect(getStageRes.data.stage_status).toBe( + SignEd25519StageStatus.ROUND_1, + ); + expect(getStageRes.data.session_state).toBe( + TssSessionState.IN_PROGRESS, + ); + } } }); @@ -277,6 +299,22 @@ describe("Ed25519 Signing", () => { expect( round2Result.data.signature_share_0.signature_share, ).toBeDefined(); + + // Verify stage status is ROUND_2 (not COMPLETED) + const getStageRes = await getTssStageWithSessionData( + pool, + round1Result.data.session_id, + TssStageType.SIGN_ED25519, + ); + expect(getStageRes.success).toBe(true); + if (getStageRes.success && getStageRes.data) { + expect(getStageRes.data.stage_status).toBe( + SignEd25519StageStatus.ROUND_2, + ); + expect(getStageRes.data.session_state).toBe( + TssSessionState.IN_PROGRESS, + ); + } } }); @@ -351,7 +389,20 @@ describe("Ed25519 Signing", () => { ); expect(round2Result.success).toBe(true); - // Second Round 2 call with same session - should fail + // Verify stage status is ROUND_2 after first Round2 call + const getStageRes = await getTssStageWithSessionData( + pool, + round1Result.data.session_id, + TssStageType.SIGN_ED25519, + ); + expect(getStageRes.success).toBe(true); + if (getStageRes.success && getStageRes.data) { + expect(getStageRes.data.stage_status).toBe( + SignEd25519StageStatus.ROUND_2, + ); + } + + // Second Round 2 call with same session - should fail (already ROUND_2) const duplicateRound2Result = await runSignEd25519Round2( pool, TEMP_ENC_SECRET, @@ -426,10 +477,24 @@ describe("Ed25519 Signing", () => { new Uint8Array(clientKeygenOutput.key_package), ); + // Verify stage status is ROUND_2 before aggregate + const getStageBeforeAggRes = await getTssStageWithSessionData( + pool, + round1Res.data.session_id, + TssStageType.SIGN_ED25519, + ); + expect(getStageBeforeAggRes.success).toBe(true); + if (getStageBeforeAggRes.success && getStageBeforeAggRes.data) { + expect(getStageBeforeAggRes.data.stage_status).toBe( + SignEd25519StageStatus.ROUND_2, + ); + } + // Complete the signing with Aggregate const aggRes = await runSignEd25519Aggregate(pool, TEMP_ENC_SECRET, { email: TEST_EMAIL, wallet_id: walletId, + session_id: round1Res.data.session_id, msg: [...testMessage], all_commitments: allCommitments, all_signature_shares: allShares, @@ -437,6 +502,22 @@ describe("Ed25519 Signing", () => { }); expect(aggRes.success).toBe(true); + // Verify stage status is COMPLETED after aggregate + const getStageAfterAggRes = await getTssStageWithSessionData( + pool, + round1Res.data.session_id, + TssStageType.SIGN_ED25519, + ); + expect(getStageAfterAggRes.success).toBe(true); + if (getStageAfterAggRes.success && getStageAfterAggRes.data) { + expect(getStageAfterAggRes.data.stage_status).toBe( + SignEd25519StageStatus.COMPLETED, + ); + expect(getStageAfterAggRes.data.session_state).toBe( + TssSessionState.COMPLETED, + ); + } + // Now try to use the COMPLETED session for Round2 - should fail const newClientR1 = clientRunSignRound1Ed25519( new Uint8Array(clientKeygenOutput.key_package), @@ -546,6 +627,7 @@ describe("Ed25519 Signing", () => { const aggregateRequest: SignEd25519AggregateRequest = { email: TEST_EMAIL, wallet_id: walletId, + session_id: serverRound1Result.data.session_id, msg: [...testMessage], all_commitments: allCommitments, all_signature_shares: allSignatureShares, @@ -562,6 +644,22 @@ describe("Ed25519 Signing", () => { expect(aggregateResult.data.signature).toBeDefined(); expect(aggregateResult.data.signature.length).toBe(64); + // Verify stage status is COMPLETED after aggregate + const getStageRes = await getTssStageWithSessionData( + pool, + serverRound1Result.data.session_id, + TssStageType.SIGN_ED25519, + ); + expect(getStageRes.success).toBe(true); + if (getStageRes.success && getStageRes.data) { + expect(getStageRes.data.stage_status).toBe( + SignEd25519StageStatus.COMPLETED, + ); + expect(getStageRes.data.session_state).toBe( + TssSessionState.COMPLETED, + ); + } + // Verify the signature const isValid = runVerifyEd25519( testMessage, @@ -598,6 +696,7 @@ describe("Ed25519 Signing", () => { const aggregateRequest: SignEd25519AggregateRequest = { email: TEST_EMAIL, wallet_id: createWalletRes.data.wallet_id, + session_id: "00000000-0000-0000-0000-000000000000", // Dummy session_id for error test msg: [1, 2, 3], all_commitments: [], all_signature_shares: [], @@ -622,6 +721,7 @@ describe("Ed25519 Signing", () => { const aggregateRequest: SignEd25519AggregateRequest = { email: TEST_EMAIL, wallet_id: "00000000-0000-0000-0000-000000000000", + session_id: "00000000-0000-0000-0000-000000000000", // Dummy session_id for error test msg: [1, 2, 3], all_commitments: [], all_signature_shares: [], @@ -715,10 +815,23 @@ describe("Ed25519 Signing", () => { new Uint8Array(clientKeygenOutput.key_package), ); + // Verify stage status is ROUND_2 before aggregate + const getStageBeforeAggRes = await getTssStageWithSessionData( + pool, + round1Res.data.session_id, + TssStageType.SIGN_ED25519, + ); + if (getStageBeforeAggRes.success && getStageBeforeAggRes.data) { + expect(getStageBeforeAggRes.data.stage_status).toBe( + SignEd25519StageStatus.ROUND_2, + ); + } + // Aggregate const aggRes = await runSignEd25519Aggregate(pool, TEMP_ENC_SECRET, { email: TEST_EMAIL, wallet_id: walletId, + session_id: round1Res.data.session_id, msg: [...message], all_commitments: allCommitments, all_signature_shares: allShares, @@ -727,6 +840,21 @@ describe("Ed25519 Signing", () => { expect(aggRes.success).toBe(true); if (!aggRes.success) continue; + // Verify stage status is COMPLETED after aggregate + const getStageAfterAggRes = await getTssStageWithSessionData( + pool, + round1Res.data.session_id, + TssStageType.SIGN_ED25519, + ); + if (getStageAfterAggRes.success && getStageAfterAggRes.data) { + expect(getStageAfterAggRes.data.stage_status).toBe( + SignEd25519StageStatus.COMPLETED, + ); + expect(getStageAfterAggRes.data.session_state).toBe( + TssSessionState.COMPLETED, + ); + } + // Verify const isValid = runVerifyEd25519( message, diff --git a/backend/tss_api/src/api/sign_ed25519/index.ts b/backend/tss_api/src/api/sign_ed25519/index.ts index f46df7f64..2e33a2704 100644 --- a/backend/tss_api/src/api/sign_ed25519/index.ts +++ b/backend/tss_api/src/api/sign_ed25519/index.ts @@ -289,19 +289,18 @@ export async function runSignEd25519Round2( allCommitments, ); - // Update stage and session atomically const updateRes = await updateTssStageWithSessionState( db, stage.stage_id, session_id, { - stage_status: SignEd25519StageStatus.COMPLETED, + stage_status: SignEd25519StageStatus.ROUND_2, stage_data: { ...stageData, signature_share: round2Result.signature_share, }, }, - TssSessionState.COMPLETED, + TssSessionState.IN_PROGRESS, ); if (!updateRes.success) { return { @@ -338,6 +337,7 @@ export async function runSignEd25519Aggregate( const { email, wallet_id, + session_id, msg, all_commitments, all_signature_shares, @@ -399,6 +399,39 @@ export async function runSignEd25519Aggregate( }; } + // Get stage with session data to update status after aggregate + const getStageRes = await getTssStageWithSessionData( + db, + session_id, + TssStageType.SIGN_ED25519, + ); + if (getStageRes.success === false) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to get TSS stage: ${getStageRes.err}`, + }; + } + const stage = getStageRes.data; + + // Validate session + if (!validateTssSession(stage, wallet_id)) { + return { + success: false, + code: "INVALID_TSS_SESSION", + msg: "Invalid session state or wallet mismatch", + }; + } + + // Validate stage status (should be ROUND_2) + if (!validateTssStage(stage, SignEd25519StageStatus.ROUND_2)) { + return { + success: false, + code: "INVALID_TSS_SESSION", + msg: "Round 2 state not found. Please call round2 first.", + }; + } + // Aggregate signature const aggregateResult = runAggregateEd25519( new Uint8Array(msg), @@ -407,6 +440,29 @@ export async function runSignEd25519Aggregate( publicKeyPackageBytes, ); + // Update stage and session to COMPLETED after successful aggregate + const stageData = stage.stage_data as SignEd25519StageData; + const updateRes = await updateTssStageWithSessionState( + db, + stage.stage_id, + session_id, + { + stage_status: SignEd25519StageStatus.COMPLETED, + stage_data: { + ...stageData, + signature: aggregateResult.signature, + }, + }, + TssSessionState.COMPLETED, + ); + if (!updateRes.success) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to update TSS stage: ${updateRes.err}`, + }; + } + return { success: true, data: { diff --git a/backend/tss_api/src/routes/sign_ed25519.ts b/backend/tss_api/src/routes/sign_ed25519.ts index d24264eb1..8986a47d2 100644 --- a/backend/tss_api/src/routes/sign_ed25519.ts +++ b/backend/tss_api/src/routes/sign_ed25519.ts @@ -328,6 +328,7 @@ export function setSignEd25519Routes(router: Router) { schema: { type: "object", properties: { + session_id: { type: "string", format: "uuid" }, msg: { type: "array", items: { type: "number" } }, all_commitments: { type: "array", @@ -359,6 +360,7 @@ export function setSignEd25519Routes(router: Router) { }, }, required: [ + "session_id", "msg", "all_commitments", "all_signature_shares", @@ -417,6 +419,7 @@ export function setSignEd25519Routes(router: Router) { { email: user.email.toLowerCase(), wallet_id: user.wallet_id, + session_id: body.session_id, msg: body.msg, all_commitments: body.all_commitments, all_signature_shares: body.all_signature_shares, diff --git a/common/oko_types/src/tss/sign_ed25519.ts b/common/oko_types/src/tss/sign_ed25519.ts index 5188c817a..221e04a52 100644 --- a/common/oko_types/src/tss/sign_ed25519.ts +++ b/common/oko_types/src/tss/sign_ed25519.ts @@ -38,6 +38,7 @@ export type SignEd25519Round2Body = { export interface SignEd25519AggregateRequest { email: string; wallet_id: string; + session_id: string; msg: number[]; all_commitments: CommitmentEntry[]; all_signature_shares: SignatureShareEntry[]; @@ -49,6 +50,7 @@ export interface SignEd25519AggregateResponse { } export type SignEd25519AggregateBody = { + session_id: string; msg: number[]; all_commitments: CommitmentEntry[]; all_signature_shares: SignatureShareEntry[]; From 7bfb41b47985cc4b98a9ad1bd07845ca43c68e2a Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 19:11:32 +0900 Subject: [PATCH 15/17] teddsa_hooks: refactor runTeddsaSign --- crypto/teddsa/api_lib/tsconfig.json | 17 ++- crypto/teddsa/teddsa_hooks/package.json | 1 + crypto/teddsa/teddsa_hooks/src/sign.ts | 133 ++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 4 deletions(-) diff --git a/crypto/teddsa/api_lib/tsconfig.json b/crypto/teddsa/api_lib/tsconfig.json index c8c92cbd6..1b280ecd1 100644 --- a/crypto/teddsa/api_lib/tsconfig.json +++ b/crypto/teddsa/api_lib/tsconfig.json @@ -1,8 +1,17 @@ { - "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src" + "outDir": "dist", + "sourceMap": true, + "target": "esnext", + "module": "esnext", + "moduleResolution": "bundler", + "esModuleInterop": true, + "verbatimModuleSyntax": true, + "forceConsistentCasingInFileNames": true, + "noImplicitAny": true, + "strict": true, + "skipLibCheck": true, + "noEmit": true }, - "include": ["src/**/*"] + "include": ["./*.js", "src/**/*.ts"] } diff --git a/crypto/teddsa/teddsa_hooks/package.json b/crypto/teddsa/teddsa_hooks/package.json index 744efbca8..9f2b0c40e 100644 --- a/crypto/teddsa/teddsa_hooks/package.json +++ b/crypto/teddsa/teddsa_hooks/package.json @@ -6,6 +6,7 @@ "@oko-wallet/bytes": "^0.0.3-alpha.65", "@oko-wallet/frost-ed25519-keplr-wasm": "workspace:*", "@oko-wallet/stdlib-js": "^0.0.2-rc.42", + "@oko-wallet/teddsa-api-lib": "workspace:*", "@oko-wallet/teddsa-interface": "workspace:*", "@oko-wallet/teddsa-wasm-mock": "workspace:*" }, diff --git a/crypto/teddsa/teddsa_hooks/src/sign.ts b/crypto/teddsa/teddsa_hooks/src/sign.ts index 786a69106..c67f26400 100644 --- a/crypto/teddsa/teddsa_hooks/src/sign.ts +++ b/crypto/teddsa/teddsa_hooks/src/sign.ts @@ -9,6 +9,11 @@ import type { KeyPackageRaw, PublicKeyPackageRaw, } from "@oko-wallet/teddsa-interface"; +import { + reqSignEd25519Round1, + reqSignEd25519Round2, + reqSignEd25519Aggregate, +} from "@oko-wallet/teddsa-api-lib"; import type { TeddsaKeygenOutputBytes } from "./types"; @@ -104,6 +109,134 @@ export function teddsaVerify( } } +export async function runTeddsaSign( + endpoint: string, + message: Uint8Array, + keyPackage: KeyPackageRaw, + authToken: string, + getIsAborted: () => boolean, +): Promise> { + if (getIsAborted()) { + return { success: false, err: { type: "aborted" } }; + } + + // Round 1: Generate client commitments locally + const round1Result = teddsaSignRound1(keyPackage); + if (!round1Result.success) { + return { success: false, err: { type: "error", msg: round1Result.err } }; + } + + const clientCommitment: CommitmentEntry = { + identifier: round1Result.data.identifier, + commitments: round1Result.data.commitments, + }; + + // Send message to server to initiate Round 1 and get server commitments + if (getIsAborted()) { + return { success: false, err: { type: "aborted" } }; + } + + const round1Resp = await reqSignEd25519Round1( + endpoint, + { msg: [...message] }, + authToken, + ); + if (round1Resp.success === false) { + return { + success: false, + err: { type: "error", msg: round1Resp.msg }, + }; + } + + const { session_id: sessionId, commitments_0: serverCommitment } = + round1Resp.data; + + // Combine and sort commitments by identifier + const allCommitments: CommitmentEntry[] = [ + clientCommitment, + serverCommitment, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Round 2: Send client commitments to server and get server signature share + if (getIsAborted()) { + return { success: false, err: { type: "aborted" } }; + } + + const round2Resp = await reqSignEd25519Round2( + endpoint, + { + session_id: sessionId, + commitments_1: clientCommitment, + }, + authToken, + ); + if (round2Resp.success === false) { + return { + success: false, + err: { type: "error", msg: round2Resp.msg }, + }; + } + + const serverSignatureShare: SignatureShareEntry = + round2Resp.data.signature_share_0; + + // Generate client signature share locally + if (getIsAborted()) { + return { success: false, err: { type: "aborted" } }; + } + + const round2Result = teddsaSignRound2( + message, + keyPackage, + new Uint8Array(round1Result.data.nonces), + allCommitments, + ); + if (!round2Result.success) { + return { success: false, err: { type: "error", msg: round2Result.err } }; + } + + const clientSignatureShare: SignatureShareEntry = { + identifier: round2Result.data.identifier, + signature_share: round2Result.data.signature_share, + }; + + // Combine and sort signature shares by identifier + const allSignatureShares: SignatureShareEntry[] = [ + clientSignatureShare, + serverSignatureShare, + ].sort((a, b) => (a.identifier[0] ?? 0) - (b.identifier[0] ?? 0)); + + // Aggregate: Send all data to server to get final signature + if (getIsAborted()) { + return { success: false, err: { type: "aborted" } }; + } + + // Extract user_verifying_share from keyPackage + const userVerifyingShare = keyPackage.verifying_share; + + const aggregateResp = await reqSignEd25519Aggregate( + endpoint, + { + session_id: sessionId, + msg: [...message], + all_commitments: allCommitments, + all_signature_shares: allSignatureShares, + user_verifying_share: userVerifyingShare, + }, + authToken, + ); + if (aggregateResp.success === false) { + return { + success: false, + err: { type: "error", msg: aggregateResp.msg }, + }; + } + + const signature = new Uint8Array(aggregateResp.data.signature); + + return { success: true, data: signature }; +} + export async function runTeddsaSignLocal( message: Uint8Array, keygen1: TeddsaKeygenOutputBytes, From 53720604597721be42b5c680730e391a35c898c2 Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Fri, 9 Jan 2026 20:22:07 +0900 Subject: [PATCH 16/17] o --- yarn.lock | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index a97c802d3..e76947ce2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11281,7 +11281,7 @@ __metadata: languageName: unknown linkType: soft -"@oko-wallet/teddsa-api-lib@workspace:crypto/teddsa/api_lib": +"@oko-wallet/teddsa-api-lib@workspace:*, @oko-wallet/teddsa-api-lib@workspace:crypto/teddsa/api_lib": version: 0.0.0-use.local resolution: "@oko-wallet/teddsa-api-lib@workspace:crypto/teddsa/api_lib" dependencies: @@ -11310,6 +11310,7 @@ __metadata: "@oko-wallet/bytes": "npm:^0.0.3-alpha.65" "@oko-wallet/frost-ed25519-keplr-wasm": "workspace:*" "@oko-wallet/stdlib-js": "npm:^0.0.2-rc.42" + "@oko-wallet/teddsa-api-lib": "workspace:*" "@oko-wallet/teddsa-interface": "workspace:*" "@oko-wallet/teddsa-wasm-mock": "workspace:*" "@types/node": "npm:^24.10.1" From 17d8f90aabd92271710e32e2475a2ad883daee8f Mon Sep 17 00:00:00 2001 From: chihunmanse Date: Tue, 13 Jan 2026 13:28:54 +0900 Subject: [PATCH 17/17] tss_api: refactor wallet ed25519 --- .../tss_api/src/api/wallet_ed25519/index.ts | 39 ++++++++++++++----- backend/tss_api/src/routes/wallet_ed25519.ts | 22 ++++++++++- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/backend/tss_api/src/api/wallet_ed25519/index.ts b/backend/tss_api/src/api/wallet_ed25519/index.ts index 107c2a360..30a21876e 100644 --- a/backend/tss_api/src/api/wallet_ed25519/index.ts +++ b/backend/tss_api/src/api/wallet_ed25519/index.ts @@ -8,10 +8,12 @@ import { Participant, participantToIdentifier, } from "@oko-wallet/teddsa-interface"; +import { reconstructPublicKeyPackageEd25519 } from "@oko-wallet/teddsa-addon/src/server"; export interface WalletEd25519PublicInfoRequest { user_identifier: string; auth_type: AuthType; + user_verifying_share: number[]; // P0's verifying_share (32 bytes) } export interface WalletEd25519PublicInfoResponse { @@ -31,7 +33,7 @@ export async function getWalletEd25519PublicInfo( request: WalletEd25519PublicInfoRequest, ): Promise> { try { - const { user_identifier, auth_type } = request; + const { user_identifier, auth_type, user_verifying_share } = request; // Get user const getUserRes = await getUserByEmailAndAuthType( @@ -77,25 +79,44 @@ export async function getWalletEd25519PublicInfo( } const wallet = getWalletRes.data; - // Decrypt the stored key package data + // Decrypt stored shares const encryptedShare = wallet.enc_tss_share.toString("utf-8"); const decryptedShare = await decryptDataAsync( encryptedShare, encryptionSecret, ); - const keyPackageData = JSON.parse(decryptedShare) as { - key_package: number[]; - public_key_package: number[]; - identifier: number[]; + const storedShares = JSON.parse(decryptedShare) as { + signing_share: number[]; + verifying_share: number[]; }; - // Return public info for client key recovery - // Server stores keygen_2 (P1), but client needs identifier for P0 + // Reconstruct public_key_package from user and server verifying_shares + const userIdentifier = participantToIdentifier(Participant.P0); + const serverIdentifier = participantToIdentifier(Participant.P1); + const verifyingKey = Array.from(wallet.public_key); + + let publicKeyPackageBytes: Uint8Array; + try { + publicKeyPackageBytes = reconstructPublicKeyPackageEd25519( + new Uint8Array(user_verifying_share), + new Uint8Array(userIdentifier), + new Uint8Array(storedShares.verifying_share), + new Uint8Array(serverIdentifier), + new Uint8Array(verifyingKey), + ); + } catch (error) { + return { + success: false, + code: "UNKNOWN_ERROR", + msg: `Failed to reconstruct public_key_package: ${error instanceof Error ? error.message : String(error)}`, + }; + } + return { success: true, data: { public_key: wallet.public_key.toString("hex"), - public_key_package: keyPackageData.public_key_package, + public_key_package: Array.from(publicKeyPackageBytes), identifier: participantToIdentifier(Participant.P0), }, }; diff --git a/backend/tss_api/src/routes/wallet_ed25519.ts b/backend/tss_api/src/routes/wallet_ed25519.ts index a32ad738c..3ee93bd34 100644 --- a/backend/tss_api/src/routes/wallet_ed25519.ts +++ b/backend/tss_api/src/routes/wallet_ed25519.ts @@ -30,6 +30,24 @@ export function setWalletEd25519Routes(router: Router) { security: [{ oauthAuth: [] }], request: { headers: OAuthHeaderSchema, + body: { + required: true, + content: { + "application/json": { + schema: { + type: "object", + properties: { + user_verifying_share: { + type: "array", + items: { type: "number" }, + description: "P0's verifying_share (32 bytes)", + }, + }, + required: ["user_verifying_share"], + }, + }, + }, + }, }, responses: { 200: { @@ -76,7 +94,7 @@ export function setWalletEd25519Routes(router: Router) { oauthMiddleware, tssActivateMiddleware, async ( - req: OAuthAuthenticatedRequest>, + req: OAuthAuthenticatedRequest<{ user_verifying_share: number[] }>, res: Response< OkoApiResponse, OAuthLocals @@ -84,6 +102,7 @@ export function setWalletEd25519Routes(router: Router) { ) => { const state = req.app.locals; const oauthUser = res.locals.oauth_user; + const body = req.body; const user_identifier = oauthUser?.user_identifier; if (!user_identifier) { @@ -101,6 +120,7 @@ export function setWalletEd25519Routes(router: Router) { { user_identifier, auth_type: oauthUser.type, + user_verifying_share: body.user_verifying_share, }, );