From 2682b91652aee04aa1ca935461114d202668f072 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 18 Jul 2024 16:20:20 +0200 Subject: [PATCH 1/6] Quick and dirty analysis on viability of codex side chain --- analysis/sidechain.md | 127 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 analysis/sidechain.md diff --git a/analysis/sidechain.md b/analysis/sidechain.md new file mode 100644 index 0000000..8118c3e --- /dev/null +++ b/analysis/sidechain.md @@ -0,0 +1,127 @@ +Codex side chain +================ + +This document looks at the economic viability of running an Ethereum side chain +that is specifically tailored for the Codex marketplace. Existing Ethereum +[rollups][1] and side chains seem to be too expensive by about a factor of 100 +for our current storage proof scheme (without proof aggregation). We'd like to +find out if running our own side chain could sufficiently lower the transactions +costs. + +[1]: ../evaluations/rollups.md + +EVM opcode pricing +------------------ + +Ethereum transactions consist of EVM operations. Each operation is priced in +amount of gas. Some operations [are more expensive than others][2], mainly +because they require more resources (cpu, storage) than others. Gas costs are +also specifically engineered to withstand DoS attacks on validators. + +Tweaking the gas prices of EVM opcodes does not seem to be the most viable path +to lowering transaction costs, because it only determines how expensive +operations are relative to one another, they don't determine the actual price. +It is also difficult to oversee the security risks. + +[2]: https://notes.ethereum.org/@poemm/evm384-update5#Background-on-EVM-Gas-Costs + +Gas pricing +----------- + +The biggest factor that determines the actual costs of transactions is the gas +price. The transaction costs is [determined according to the following +formula][3] as specified by [EIP-1559][4]: + +`fee = units of gas used * (base fee + priority fee)` + +The base fee is calculated based on how full the latest blocks are. If they are +above the target block size of 15 million gas, then the base fee increases. If +they are below the target block size, then the base fee decreases. +The base fee is burned when the transaction is included. + +The priority fee is set by the transaction sender, and goes to the validators. +It is a mechanism for validators to prioritize transactions. It also acts as an +incentive for validators to not produce empty blocks. + +Both priority base fee and transaction fee go up when there is more demand +(submitted transactions) than there is supply (maximum transactions per second). +This is the main reason why transactions are as expensive as they are: + +"No transaction fee mechanism, EIP-1559 or otherwise, is likely to substantially +decrease average transaction fees; persistently high transaction fees is a +scalability problem, not a mechanism design problem" -- [Tim Roughgarden][5] + +[3]: https://ethereum.org/en/developers/docs/gas/#how-are-gas-fees-calculated +[4]: https://eips.ethereum.org/EIPS/eip-1559 +[5]: http://timroughgarden.org/papers/eip1559.pdf + + +The scalability problem +----------------------- + +Ultimately high transaction costs is a scalability issue. And unfortunately +there are [no easy solutions][6] for increasing the amount of transactions that +the chain can handle. For instance, just increasing the block size introduces +several issues. Increasing block size increases the amount of resources that +validators need (cpu, memory, storage, bandwidth). This means that it becomes +more expensive to run a validator, which leads to a decrease in the number of +validators, and an increase in centralization. It also increases block time, +because there is more time needed to dissemminate the block. And this actually +decreases the capacity of the network in terms of transactions per second, which +counters the positive effect that you get from increasing the block size. + +[6]: https://cryptonews.com/news/contrary-to-musk-s-idea-you-can-t-just-increase-block-size-s-10426.htm + +Validator costs +--------------- + +To get an idea of the actual costs for running a chain, we estimate the hardware +costs associated with executing one gas. This should give us an idea of the +lowest price at which it is still economically viable to run validators. + +Back of envelope calculations + +Pylogon PoS: +- has about 100 validators +- requires [amazon m5d.4xlarge][8] +- which costs [$285][9] per month +- gas limit is `30 000 0000` +- in a month there are approximately `1 100 000 000` blocks +- which means costs per gas are `100 * $285 / (30 000 0000 * 1 100 000 000) = $ 0.0000000000008` +- while average gas price is `$0.00000002` (a factor of 25000 higher than the cost) + +Ethereum: +- has about 1 000 000 validators +- validator costs: [$20 / month][7] +- gas limit is 15 000 0000 on average +- in a month there are approximately 215 000 blocks +- which means costs per gas are 1 000 000 * $20 / (15 000 000 * 215 000) = $ 0.000006 +- while current gas price is $0.000035 (a factor of 6 higher than the cost) + +TODO: check calculations + +It seems that Ethereum gas price is about 1 order of magnitude higher than the +the actual costs for the resources required. + +The Polygon PoS gas price is about 4 orders of magnitude higher than the actual +costs for the resources needed. + +[7]: https://www.launchnodes.com/ln_products/ethereum-validator-node-prysmatic-client/ +[8]: https://docs.polygon.technology/pos/how-to/validator/validator-system-requirements/#recommended-system-requirements +[9]: https://instances.vantage.sh/aws/ec2/m5d.4xlarge + +Conclusion +---------- + +The main reason why transactions are too expensive on existing chains and +rollups is because they are utilized to their capacity. This creates a higher +demand than there is supply, increasing prices. The actual costs of running a +chain seem to be ok for running the Codex marketplace, but we need to either +increase capacity or limit the amount of transactions to ensure that transaction +prices do not become too high. + +So it seem to be viable to start with a side chain for Codex, while there is no +high demand yet. This gives us time to work on reducing the number of +transactions (by aggregating proofs for instance), and increasing the +transactions per second (by sharding for instance) as the Codex network becomes +more popular. \ No newline at end of file From 9ffea48c64fc4cd799299c3e28a1113888117020 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 14 Aug 2024 15:09:36 +0200 Subject: [PATCH 2/6] Evaluation of existing side chains Fixed errors in network cost calculation --- analysis/sidechain.md | 127 ------------------------- evaluations/rollups.md | 10 +- evaluations/rollups.ods | Bin 31154 -> 31156 bytes evaluations/sidechains.md | 185 +++++++++++++++++++++++++++++++++++++ evaluations/sidechains.ods | Bin 0 -> 20325 bytes 5 files changed, 190 insertions(+), 132 deletions(-) delete mode 100644 analysis/sidechain.md create mode 100644 evaluations/sidechains.md create mode 100644 evaluations/sidechains.ods diff --git a/analysis/sidechain.md b/analysis/sidechain.md deleted file mode 100644 index 8118c3e..0000000 --- a/analysis/sidechain.md +++ /dev/null @@ -1,127 +0,0 @@ -Codex side chain -================ - -This document looks at the economic viability of running an Ethereum side chain -that is specifically tailored for the Codex marketplace. Existing Ethereum -[rollups][1] and side chains seem to be too expensive by about a factor of 100 -for our current storage proof scheme (without proof aggregation). We'd like to -find out if running our own side chain could sufficiently lower the transactions -costs. - -[1]: ../evaluations/rollups.md - -EVM opcode pricing ------------------- - -Ethereum transactions consist of EVM operations. Each operation is priced in -amount of gas. Some operations [are more expensive than others][2], mainly -because they require more resources (cpu, storage) than others. Gas costs are -also specifically engineered to withstand DoS attacks on validators. - -Tweaking the gas prices of EVM opcodes does not seem to be the most viable path -to lowering transaction costs, because it only determines how expensive -operations are relative to one another, they don't determine the actual price. -It is also difficult to oversee the security risks. - -[2]: https://notes.ethereum.org/@poemm/evm384-update5#Background-on-EVM-Gas-Costs - -Gas pricing ------------ - -The biggest factor that determines the actual costs of transactions is the gas -price. The transaction costs is [determined according to the following -formula][3] as specified by [EIP-1559][4]: - -`fee = units of gas used * (base fee + priority fee)` - -The base fee is calculated based on how full the latest blocks are. If they are -above the target block size of 15 million gas, then the base fee increases. If -they are below the target block size, then the base fee decreases. -The base fee is burned when the transaction is included. - -The priority fee is set by the transaction sender, and goes to the validators. -It is a mechanism for validators to prioritize transactions. It also acts as an -incentive for validators to not produce empty blocks. - -Both priority base fee and transaction fee go up when there is more demand -(submitted transactions) than there is supply (maximum transactions per second). -This is the main reason why transactions are as expensive as they are: - -"No transaction fee mechanism, EIP-1559 or otherwise, is likely to substantially -decrease average transaction fees; persistently high transaction fees is a -scalability problem, not a mechanism design problem" -- [Tim Roughgarden][5] - -[3]: https://ethereum.org/en/developers/docs/gas/#how-are-gas-fees-calculated -[4]: https://eips.ethereum.org/EIPS/eip-1559 -[5]: http://timroughgarden.org/papers/eip1559.pdf - - -The scalability problem ------------------------ - -Ultimately high transaction costs is a scalability issue. And unfortunately -there are [no easy solutions][6] for increasing the amount of transactions that -the chain can handle. For instance, just increasing the block size introduces -several issues. Increasing block size increases the amount of resources that -validators need (cpu, memory, storage, bandwidth). This means that it becomes -more expensive to run a validator, which leads to a decrease in the number of -validators, and an increase in centralization. It also increases block time, -because there is more time needed to dissemminate the block. And this actually -decreases the capacity of the network in terms of transactions per second, which -counters the positive effect that you get from increasing the block size. - -[6]: https://cryptonews.com/news/contrary-to-musk-s-idea-you-can-t-just-increase-block-size-s-10426.htm - -Validator costs ---------------- - -To get an idea of the actual costs for running a chain, we estimate the hardware -costs associated with executing one gas. This should give us an idea of the -lowest price at which it is still economically viable to run validators. - -Back of envelope calculations - -Pylogon PoS: -- has about 100 validators -- requires [amazon m5d.4xlarge][8] -- which costs [$285][9] per month -- gas limit is `30 000 0000` -- in a month there are approximately `1 100 000 000` blocks -- which means costs per gas are `100 * $285 / (30 000 0000 * 1 100 000 000) = $ 0.0000000000008` -- while average gas price is `$0.00000002` (a factor of 25000 higher than the cost) - -Ethereum: -- has about 1 000 000 validators -- validator costs: [$20 / month][7] -- gas limit is 15 000 0000 on average -- in a month there are approximately 215 000 blocks -- which means costs per gas are 1 000 000 * $20 / (15 000 000 * 215 000) = $ 0.000006 -- while current gas price is $0.000035 (a factor of 6 higher than the cost) - -TODO: check calculations - -It seems that Ethereum gas price is about 1 order of magnitude higher than the -the actual costs for the resources required. - -The Polygon PoS gas price is about 4 orders of magnitude higher than the actual -costs for the resources needed. - -[7]: https://www.launchnodes.com/ln_products/ethereum-validator-node-prysmatic-client/ -[8]: https://docs.polygon.technology/pos/how-to/validator/validator-system-requirements/#recommended-system-requirements -[9]: https://instances.vantage.sh/aws/ec2/m5d.4xlarge - -Conclusion ----------- - -The main reason why transactions are too expensive on existing chains and -rollups is because they are utilized to their capacity. This creates a higher -demand than there is supply, increasing prices. The actual costs of running a -chain seem to be ok for running the Codex marketplace, but we need to either -increase capacity or limit the amount of transactions to ensure that transaction -prices do not become too high. - -So it seem to be viable to start with a side chain for Codex, while there is no -high demand yet. This gives us time to work on reducing the number of -transactions (by aggregating proofs for instance), and increasing the -transactions per second (by sharding for instance) as the Codex network becomes -more popular. \ No newline at end of file diff --git a/evaluations/rollups.md b/evaluations/rollups.md index 3c28b35..d9f5006 100644 --- a/evaluations/rollups.md +++ b/evaluations/rollups.md @@ -55,15 +55,15 @@ And there's Taiko, which uses a combination of zero-knowledge proofs and fraud proofs to keep the network honest: - Taiko -Gas costs ---------- +Gas prices +---------- -A rough approximation of average gas costs for submitting a Codex storage proof +A rough approximation of average gas prices for submitting a Codex storage proof for each rollup: -| Rollup | Average proof costs | Potential profit | +| Rollup | Average proof price | Potential profit | | ------------------- | ------------------ | ---------------- | -| Mantle | $0.0000062723 | $2.58 | +| Mantle | $0.0000062723 | $2.58 | | Boba network | $0.0016726250 | -$2.54 | | Immutable zkEVM | $0.0073595500 | -$20.01 | | Arbitrum | $0.0083631250 | -$23.09 | diff --git a/evaluations/rollups.ods b/evaluations/rollups.ods index fca9bbae0873a05012a0d9066c3b087c25d82e2a..153c1649806d3eccc54e4ff3c4bda9502c1802ee 100644 GIT binary patch delta 5080 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 delta 4961 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�j)T5jTOwYO)f5@pIy$8gztIe`Wu0|HuWj*fE{(!6id*XZ%^B?8NsjQV=7E!6oO8O#4=_WgFC-kn(fj^-D)J zH>7+nwM?o;TQ-%9l#=i}>AHL*xgH&*FST(bM}3J3e+<(+Rh@fcF+nR_W;`)^TcM-a z&AOL{B)^h{sx#U1sp4N3x%QXEQ-FhEbrEwufu6j4lCAFfM79d;nd%eJxF>DC~SylM;+FP|>3PX1mIRAL+}* zlg3kcZk%4*)_3?G6W?$?O9v8Pg)cYw3Fuu#k2rw7NE-*0gn~NnMQl>ztAqSG?IGrR z;r19>;-d)HPasI?4V%z2a43Aie~Z>=7@d{xjvM*to(7BO3vcQ-*gVVUDDyf_(}Biu zJlR#Miw7Q;kf(>Tn(Ndxi8#nIvhJ9dz&jr4IGW~9WA)m<*RV^tbA;NjI%ja1|U?Gl8I&uhN>@(ae77IWdRW={y0 z@ug1)&IR=jH_=s;!n^H#s#t=F>p6-rcu&@XK?3O-W>;@dZ<4LlrIqXiwG~Cf*n-;g z=td`j#A{^Y-&vq-Kxe^BGZBNOIlAzYCF8>G z?6!bm!=AHaG_;_n+U)kChJx_zP&ar3QO2V0+@br|YN&gg-tuKIeC!&(cH3;$ee@Fw zNwV^xoknDBSoyh$!HrH;r@Q-xHLxSpmhPsX-RsUpLek6#pu=qTb&)7RU&&R8X~&Cl z3b`IJN4N_KTbZy9bIalOj8{^ug4Jf1yJl@txvP19=Um5_p**Y^C){MZvdYh>OyvBU z@ZjNlCpyi*{aKeaYxq~_KyBHXu9@IuXcy)<)AY{jGgl|Wrrg78)lMQPzn3(S#`=MX zhRJFwnUn;nq}mUQdXzugtumy^+7|sI@AKzv?h7(qitSnf?(_T0navK|b^+h?&gp;c*NUS0 zh}0_}5Fh8C{rZo1QyIr9srmb_dl>2Qx1gek`mMWQThVmb7bvQqst(nSKMc^n4(5M7 zgFw$f*jP00Z%roMiw>s;gaxCiu_oxNzij}D4h(sY=J+o{42)F;Gm(OEs6hYKlYV8z zaR*~vy>9;(Sp>#R|3Bc*fH;d_>;mf6KM8PXaWHNSe@FZyEno?~?-BfxsQywPu!`P) zH`3RePR#D-upm8soNbVIyb;do%D>z4hxzXh9nt@E)*jpIO-J%8=s$ytJ@Dpb{$=5k pyp~F$2?G5(Y5s>5gq8C7yZ=r;bU1BD>;m#SHp7P;DuVh2{12HD8vp?veRpHCA~UiorL1_%h~pZxa`kd?WWv7?)z}!&Z(cH$G z*4f&K#zx=4+=0f%*4Wy}#?Z;i*xHfC!Peeb-^jtt*w|6-|LXH^H~*cm|JDR;tWC^K zo$UYBn*#%_zM-Kp!1(X2jXmxEjKuplNOLQFQ)35O0dq$yeOrhB0LJ_`U`HDpfUUl@ zG2lPo(EkUVf&PDb)qgjdgQLEqlf!?;{X5~<+S{1g8$0|zkpFH(TN_&^+rOG|`v07t z3BX3*(fB{j@83z~pMn0*>>wZ@{A_gu0a zguRPwc49C?4N(w~xRC{EM?CaUs|=Q%NM&-mQon;fM%bx`_E3Z21C__2O` zk&sej0gnFIZ8DOBj7j(M?7g{{d&7F2^Zt2UdN-6&(<@scFhz$tJDoLGTK?OfiDvFs zhVD-DgSXp633?d}SF&gAoNnL8Uo_L-7<<(X&O!jbseIG7nB#^!JY~^pIZ1GchG(-m z&>uiR{=h&$|9k!aJMsN%HyS(Y)3{mzA{C{h)9H{qo>lQ(s)ttifS}b%gUf;|HA>Y> zn?qJ?N;QY0BGl)6bo)eE)+hDZZ-*GKC%L5Dd^k>aFtmy*N`Ju;A^RezP|T~G*u7&M zpLBi6tre4z_)1c~0i#F5@1*M`q(wE$NNDHkZsD;L^wR|hVrwiTq6*WShXOqPvr%C1 zX7kv>DHk~Vt>#Ok(vN^}p8u>9r8t53?B0zoX-V2)I9+6Bfr<0;^{X!+U@Fwv%W9bi2+glyXaEXkKY3-^hKI=qC+LR_pdM*zfF41ZBn9@jAG}z6#B?69K z_fHe1>YW8sY%9dVRm>977g5JN-dBvn3Tu^w2GiQFEXP~e>TNcM8SNvU5O99Zk@8vl zoM3I2M$|%Z7B%(pzab92;(3&ioJhi;{gfboNo>TPHT6RQN!_Y)eD=o<;K{)wMQ19>&d7B}}p1zF^kV z_t>XI&c{H`c?>hAG{Ow-!7x>_vZdEAt<93-xzvI5@fi zj2-^b?xv=>&7KJQ*Osndhw`GgEx?uq6f?x#O0yJ8*`oxnJd~RyAIGC2^+(+2VMnX+Z-o009D?|CP;Sgch zjY>xHJ^qSyv+4Rt#0=HT13?T^cE2XB+EoN8r1gGQfIhMj|4+6XRtW2Dwa|5xX-$%$ z`c*19rSY_w4#7vZU)Vew5I__5^(lFA@PXB>ZyLho31^HR^7 z6Dq=mp2MQ>I;aVR<3MT<)0df)_KP%}Y_%nh%9yra9pqA2sp1`7Lm^v3>mh~C-Yo&B zzl$uug4g0Y44lh3(q?{R(BP6Nt83ih@@|76Ck5CiM@X}sShK!G7AFN$Ympw6_Lpg7vWs^#k22!LKIVmz`!7^1=bZ;0^Yq~1Q z$1lR)dM7FG5o1s6teZyM5{Rns25EqeY_APJy_IKx#?DTAJxUW15uhmesAzs}cVus53GEoZ4hT&wMr zeo`8LSA!?QTJ&{~?k)A`J!v0deveRI&9pnf6!e9bqHz8TRzY}J+fY}@@Y`KwIz zKFHeM+WO=nzPN|`w0~1#V>fF9{F!Wb*k7ZjxW5`QSoBmyrd5nRRHVb2??YJTTX^qUrHd(Y zU;B$s1gf@VLoZu#l?rqt-;UpzsWfp$=!*|E>+`p}%>abR=*c8gg3o66FD23pvCbgV z9UOuVHtB-4OolI3Q?7v@B6iOYi{dVeCTu~^tC=@4yplH|wucGu+CnJ#zmbg5H7+RX zai}yCM!9GY@~ug&oQgm zE2(T`14bqY1%FMNJPSTRyWV|>Q31~m)N-@I2;S4?4AyG4kmk+1J#rQX@OYuAk-_hY zFIx7n-1o@b>SJ|g@2mCrRBS%i1D~(k>nU=*mr(EQTM6{fO+X>Rk&5gZ6&|1Sn99&B#HC9QL0$; zl7+_fFC4SBlO~F#CG(n4p#-Dcs?gHA9X2qm!cLRcHzUl+a)z3j{0Y*hAb;eycsb8! z4RClxc5_9YDms2kt;kuY+@ErA9TQ(YGubTEqeW{sx;9<@W#5wlmF&RyoB46GSGj&m z0hxnsT=Mb2&U|YXN?`IYLAJHQr1_f^01EODY%$v3xTubP_+o5ORv^nehbRZnvcE+K zSapd7ym{NRH&rPQJ#{peS-fKGRPJ6pv#g9y(ey@gfn9!+8NKrUL-EBkRAuGhKtPHN z|LOM)`Y**B+E_dOV=4XR_)8p1hjo^__fM$EGv_!da-K)PMU-K?mC4=Bz*M6{W)?Up zK`2t#&W{-5$7MXAE)s>GBnm1DrVMo;RKA;o1}?Q~G1Wfa8E%!}A)(LyCeKho?u>OD7%Z z?s{S35E?~)`+9FUH*A>@55bOG2}rrGWhr1rC^^-tIii|??}oa+iyt~c1x71H=8~=0 zbr6~f&PzGvarpi`>hVapBmz$YacL3oghp=qj>(8ZWM)F}Gyp8&(ycgw9X0y) z{ob;a!=j(B4PN9rj6}l&=oxVZeq%(jLJ$~Ssad>m7D_o6i0+Xa4itEy((!jbtAJ|* zu$}z0q3jqIv(A0U(YSQdrI^6NBZ*Jb#`GCdR zvhHpcyoh+qH80pC>BG|=tfqmU(y6J*V2I`(wSi4!ETTe|(hS!gu3@qPTJMGW4wef_ zV4*-~!t;j#j716C%;Vs~DMU?S1IovNOJ@CAOQcXw{v7OOB7}Z7gx|EPnak=M=%>vrRS zTtqs8z?8O_h9NV@Xo8o#4Z)%qwP4SamSG6bU5*V(eF4rBj4E1)k)3)-_I=wCjL%#h zSoV9{kyEcuU0C*W-;vaQe&&O=U_lwIr?$nIbDS6l;QYOYC-}gOB@CFLMO!TF7(0>0 zK@KkL{U8%%=3-0m43$dVSf{sMDUf|_8#$DA!8M3U21)}LJ|g|6vbrl@kvv_u!87m% z#Luw`&YZ*(%g-=UDc+P+J+LJPid9IhBRhizwcdzCqgkkO*Inecc=E%yJ|-s~hjjTY zq>>!pHpU(D)g$C-eUt%7rb(HQ^Uq$to1&bQUAx@~D=h+*pLBi_D|?7hy&L(ILdFnK z&sR~BKjEo}JoC0(FD4(!#$ebh$lxg-ym1z7ZE&n=6P*%xPcBh%R35@F9Y8o&dRT}f zVlP`vj^4(OG`c#oYHqPz_7qggp$DLBWBF#dVE))$g5z8yJ?`QA(cITl9jS^g3EXc?0tvu)R3-v+)jxf`C$D|I4U9J=F&e?w?Z z$=Fz6qR;M=hcH_o!A%c^Xgj=)|<2oWn6lZ@Lhaad!v zQRlkQwGZ{Y&!(=8dbpN;KwUu-Zofb`NSUs@wEwmwAq9N15nBC=X_zaY{{%mf#^1>F zk3JCp9%WY3a1RkmlROL6`rWnUfyq*mNX!%V(gp)S9bjf7zs6##zG8aq#~R7mYuV=V zho8>rQV1x2Tm5t&17reZkJbR3G-_&^e!Wzdz;+}vce7SzS#M6ScnR<3#^(pb_OILi zV>uB)-`aDxVyiz~%cBXuOIaCk*EN*-^C8BJs7-1#F!T{4`x4Mxe$Jr_FP}Z-;|l{} zXQdU%Awx_|<~AxgME^c?QwU7N#h#C&z>Y>;hQuC4W+NOQcEV1fRhn^?!dJ$X#2kDa zZ*<23+2EJQ*Wbp!x2J0mj20HsM!ePA104V)n`44W|Lj?ei2e}jb*+L&L73bP$Y3LP(1RGF3M#(7S#gZgQA5ex{w%E_W@Leyt9@sHTs6tbtqDB zZ7mQ;V-3DQNVwUxoJN^g!%nwe^HIf2%GX&i?0-RN2Fa6D^=bP=9T9^E;Tq-GUr_i< zrJ!n_0cZrEdS6im12)2m2@LeKo}ZZ_v!G;#P|)!1J|P2977sDxces&(AQF(SbBXo! zLBBydV*V63pHV=_ExwbjBm2n9)~Oa#H7OUvWD z)rQz}#E{B`|6Or`BXzSDb+GD<&V9e?$(0^$dVdSx$(kG%xwq?VdKXI&Yxizca8(+f z{?0;~s_%1CVf%&%tUszUL6J#;(LJgeV~>Mv5uA2ESGVCluk;DnQjoM^5JGt#Q7=-} z`#Iq5XUoT=uCH5w2cbtR<<%xQK++D+?eWSptbs36p(b-JvXdq?~tn z&u`=1H&B9}5i;9A9Ki+7LiY0WmgK9*J$tL1W=$UUHJ+Hn<`^EG0lFnJMstNBdFV-k zr|EOOm_xmn)MPY)DaM+eLZOeuFD8s2M5!e+ULMhuNx}1ov@WA>)7z*G2AaHoYp}8y z3<>Cg#4TzX=ep;dn+V8mnss%2Gd+&HT`oVD#pC_DlUV*Lhk-8c{3TwQf0}0E{H{%I zq?cM$2>fn*zLD#4n^jKD0`+fGf zSlo<9tJ~$CYZ+9y)$#7?asR}tN{gXbWuYII2hY*($8z!vRwpGdBa~h(r2KhCv=^t1 zji%0=GfwT}Rczc{Rz9)ml(@9`@WrR2K6oQN`g!=ejtQcctTWC*RLU=H3?*&6R9MO) zqY_#awuYTqR2E1cX6*>p#(coaS%`vSGZ&H<=5n*kjRhu}Ko|duLyC0r&PsiOaD&(c z>rtpBpQlrusq$@$=dv2mZA>IEO2eQc;n9q+20wJ><+6kvN*%e<#dIK>uF^blss30B zYF0UKdD(v*NqLEG(ruP|+2KYdk_FQ9Ea(os61#AAN|hzLeqgJJ2PSmje8UnwCm3!}LCx}3zH-V;MEoc_PUIjKZK#s=Y@V&Ri(4-Ha8UNf0R`7oB~15g zqdiM9SvRn#$_L?&$lZ<$yhHm#>Xh4KIBvbcrJ@s|MBqyt6AE?PdV8U*ZE`>Df{8Ec zwcq|2CI6`|o|<)W8fkMwXgHWNHO*K65O$Df}t@?_oktG4(~X654m(i z85<&4fcrq~0PhYP7NA}%hQ8@7ie-iZ@~6@D578DZ>fuPUwG$qFtt`Xv#8K$7QX^e{ zBh7G&opa*B*vQeyf`^pF#s0najo#_j)mF_9muOMrv+IUXp7fK3&~iw3q-TZ)QW}$! z$e8VcMHsK+c8qk6OWx5Z@$1yjOw)U;b%D!h=?DBtfQ8IMa-%&?PZI^_;M3U<65^MX zEh$hXNHufBYi!zqmA{}J+8k(~?tuO_W}9fBIreE3osOV03;{xilkddowO-TEtOw9x8(l$u0IQYA2u9a6uYYR^&25`UyWU$i^y`JhM^Tjx1V9CD7?9@HE|>v zKkfg#Wh>1sOt*}Vhl)85AC@O~A6@|8Ll>OGU~HVy;bid{BH?0O$JSk`q;&uyMa%R*j1-;}{{$#7~%j3w&A-#Z9AH1VV5M zLxmEyFmRub+LQUn7^iLn2qpqS;4IV%E2M{RSB1@t88PcDohDj7-Ir2H50+A{!KY||by{-bSjq>#0YO!?`+AqAydp?Gh!fV* zMp}JX@Dumswxp$^g}4n(SADFQWbjh3O*4S;uJDW^#IZn@HBN@2vmXI_^%#7yw5UF7 zt6*K>Q~wc-@e=(wvrL_PJ@+E{S${7X`cZKG_?yj}agrcDrOP@ndr-*OU2KG*yP6r% zApoxTs`tQ)`=?;M4hKvF>2BE|{Yn?b(+xC?csJkmLr_rH6LmB|G`rU1+_BgrEq zTMpt52_#;tfd`F`qHJwvM_5|%``TuONxZ~oWXqR}{J1o0?hIv#V|aDz*}07KXR^jk z;$XKSR6xZdQ{ZC7>6}?Jl+UB}JnB3$YQ2!_7-+qZ_zV8*)Mz>qk+{h({JdfYKBx5(eVXkezj@F5snOTa*-bWAT(xBWohMd|I$D{C zT&mTjC;9x~jS>2d1!7T_$4jDaukT>&&LRRy8=v>!MNdu_VDs z+LA@BUMIsvOpR@W_BUwQVLyaLNe0=KuCJ!N4rooyWUj1V^6Rc?wl_9Opd;@LrP{(& z1D0BO!n!`=#2=uEj>lFWf7i!7J4g%?)#al}iaw$1r+rp!(C*KqKy!;iN>{j!J4^5* zPfOq~Wa^8pWNQdrPI1k!-s2k%qvJ7j(=eQ-I^7YTqUZ;IJLA{pUK=U2W&4T`nUIE7 z7)@p0j8~fwWt=jPrS=)bWicP%GUA~H!RJN$u#aTj!vwxC*PDKW|KnRxO64m470O4#tj-=GLbF3ZPtSSgG!D{QC0t2@I}&Zc*}7AD4eZF6b$PpawnETmu_P zBi$q}tm*zLqIOj+2$^wz&hp1ApdDq5e@GpjAXeQr!R1L47(yUf4veRj*o8n0ZVQR1 zhE|c~?V|c?*Ek7_5*_r^NoMx=3t>C_4gmB;8@cq2!;ugXbAm)9kne;fL*C%iLKjPU zi6w20bvM%t_r;MhMvUA$=@SO%(xCR!eIRCe=K{32kApE6yt7caNYKe=#qC15g-qFt?U|HQ32X$1!ITge|EgX5HLAcM*l4u7vl4%hT0>kW;J)!Rib~xD(U-98%C`r$AWEaNct3CQz z2{2`s%DlZxwXC6iE`EHYBcM&?v{OI@o%1Seh$03}Hp`<2QM(9B(xe#i9~@fwFzu>X|KJvAhT;Ty7bIwMOE zznQb%kql&HNh7I<9XjE*t9QbcT%bVtDBwk9mimC$&Z9mo(p z^-1I*9H(~@5*7=l(j7Kk0pnod`5MIh4P2BTqij6$&y->a z&3oH=Qz-{g9Ma@@e_oE4{C^d^J$R3#5n%hFcp?6>94`g`DmpwB*3Q``*O#L9LFh>O zr3A`1N%O=p-h@MeRvgg>SHP&a3wae6fpecp9Eo$r@LjLy&=-9}q2I4klCGCWuYHv-CEFd}jW4f|LNpV%<{9HX2NUniAVF7*wmtr2&g zOMbNYmS>C!@cpD3PEZnbh}YwzX-&jj&PwRII=N8UT?T7@?@RZ)%p>0`Ju?OA(s|V` zjqkB!9GGm45JD$8QRR^Q-qxSWyXxxt5p3|DnRvk8!#7YA4X8C!i_#Pk7xFB2hW!P; zhkdm6e7mt1vkCOW-WMLE^2dc38nr@Z@6}Bsq+U;KL52LZX^d#bG?ziS2a6+f6i{q0 z>0KZV@HDncothLA9E|BJ^jb(~uuD|$HSsd9ejTou)F#YuT-PD#J`7eX4KZ!Px)1Ob zT#Oyi))E^kBqA{;4m|-rUcv0aZwg+s`j$Hjx9FAq7sNh0yle@2;#b z?pOApy=+7ZNrEE~0fP8D>>150qdF-#(U{S~_oDf+n!1HO)^Pt{MGajUKle39#4Zjw zf7l8AqFruF90=&=o1B!A@XsGVL7-8g5wTF9Kv3WjF%Y0oP|zSz zN#Jl9k+4XA;WEJ!uwoICqmr=U!vT??fRkb))8oQX5@Ipo!?BT~6B84Ykdl*-Q&N!< zQ2r*Npr9nCWFn;DprB?Tq~oTcXQX80WTqx%q@(7gC+1|LW@cu_p%K8L6C$AHBV!RG z=ay&W5TxgpWakm2=ar}CSLG0pWEN3llQQ6zH|3|o5TeHwWhN2jW>n;%P~@SL5a3ki zr&beX(Us#dkYY8F=M)qc5tLLGSI|$dH5b!zP|z}yGH_MWvr;v2 zHc{l)R}wc?m$6h9uu>N`R}(kZQF71{vocV1GmvsMRWUTNFaS7N*tt0Y4Bc!@+?}jk z+&oZalF;RnNi{O5baQC*a+r+^WKDfl00CO|A-b-yeAcBBPL;;aAx56@?%n~~0Zo8E z$u55)oI}z~!rH83yPP9(J>p9o6MOyuRR7rOL^x>0IBWSk8v8k02Dw^0A=$S(oe?91`Xik(?OuCn+X0DLEw|KF>F?JRq$y zG%+VEtvo2RE-t+wJg+4&w<5Wutt=(5BrCBlJ+L%4r6n(-E-$vWD7C&cv$ZIpvm~Lt zBBP|Fq_DEFqOQ5Fvbepzthu?xH+v|ecsQxDKcj9avth2NWu&-$uBEfDqIapices9F zp>Alcade|~XuflNv2A>#ZF09`{;;niX{0W5q`7FIt9h=oc(k`=xvzY_zjk)0ZE>V+ zWw3UAv|(esb!(<;XQX;}s`YTLeROnWU~*w(ZhdK@e`R)Td3kAM`DkeKW`6TzYUgrt z_kMBbVsr0sZU1uh z_3LK)_~hj1;{NRZ?f!iK_VVoYYWMl(`2ObN^X~BT@$CEc`1|eR{{H^%@#W$D^X2K` z^ZnuL>+A0p`2PORjCKnH0wTZ_7vfiPUAxTm@>E((9iBEKMXHk?A?Mw1qy;` zSuonCONB`vH94B%{=RUS>Wr7#8X-=N@PB_NH#*w#nBqS6oM!)fIoRl7hr!S@{Sf0r z;LmeA@;nSeW8&gEShT)#<>=xF;mj0w%a6~WE>>22qj+WKJ?xKJzCH_?WQBxu>GQ>k zy}3JHNy(#;^>95!C);KlUs@G^KkyAwc7q&0C4QGuDJ_1Usoc6|vU)}=JkiRoaoce5 zPk`EPVTvHGNOoQIhF3i$v#H_mQc1S#P7LQ2BGe)0JVD6pmiwsT(0XTP%2Et;bTcHi zgzs~)DE9YegM!BCu*=;At`6>6(r^Ra%rodVLtOs)gu7ZDX>$LK_PKYa5E+pFr|L#t z{DcsV4Dq-%-urG%;2O-X+_%AEP^O%)P9r&A`+=gJa9DyXN(DLM~=X4L379 zeRO5Ty{q5MK(N~u>v~KNO*n5Kb!bH*OWLP82Y0iKHa>M!ZlD<}HMX-YM&^3F$eVlc z2Ex!m7oj<~0-Z78m;qSRST+tV88g)_34eG0TE2)YyOLX+JpbtyMuPGSU<5cZY6`y2 z(RysKrpWoN9<-}ZVMfOMrddqo)L}@WJz|h~=K4hO%}wbZ+=X%X^5|C@4+{#Q*(SCY z&-18Ru<)5oV@L^&tPm@(w9+Sv9Z^{-toO2J3A=y%6QI8>LUGOss93a_>IreX z=IW4lnFTW?g}&wMD1q>?nugQLkdUH)6t`1EWn2I@(*BF;g^c$kx-7K}wFY5Wdeb3_ zWCRiaH9m=fQnFm|n8~1(sgL1=q$a}(cq(8hNm2{PriDtA(I00QUQV(KZS(mhN%i-6 z@d|>)&ZOh*RKWF&*zBbc3#WTzo3Hyv^By5}0? z8uOZiKmrH-5c^h6hLMMEgj(0~3eJrJyKqlMX@8#T z3gNFqdBN26#e}R(k!Ss_`z_@qOrtdjbDzUW)`iJw7U`n6J(b;frJ;g@0gGYMBX5(3 zz-YCi^0H$LhFq{HlEx-SJo4@~{+CaZT)b7mU!|~krY)s8o1oJhJv?YHIJKIPc`iU$ z^5(I$CKrZ;H#D%APc7GX5?*?JHIzbiXZ^~TDwO1?p3Op(Kbuvrf(#nBHk|r2tggu% zT0Ad>2r#dtpve=Tk?L15gLFd1+`2YnZVx^toBepn&BXi@Y$Ihxydh$7RQhK?D|0|> zkeXx41F)!055~nL)RiC0#xH!hZfo)9WNjjf_=P#DP_A|s6KryQ&r*nV^A#Df;NVq?iIKi6KJ+lhSo@M3m0W-i0LR*6>@K9jF{CK z2s2lj(|)8;vt{+_B&)k<6Ukff_*L3j8(h%o4j5!O0q1|kOz$Or^{~H(g=|v*_N{ zO*Et>+d?OpHkUGZRJL^%CYkEG|2mqg^Vb>$_YH{JFMn-k8X4I6?7Yram}yT4cM&(m zRY$-19?wghVjy|kX|og)hL(K-YsBL0sgl*@YEqRq!pLYEz}tOQbo@TwRf~Pf`@MF7 zmiJ*^KSdJjRXknWP_Bijxo8||R9bFCUX?bV@qvS+eym88qCWxJ7IJ1UyukcfeMr%A zV57Dm5x7jvRHOgi;!!)RmvLPXi|s-1!O58&Uyj3Sk88RU{S@q`y4_gtmiH2jyIIf(jP-dZnA~;x zh#ixu@_atF+R!h?rMgxx49spZzXJ$+kK%p(urXv?cf@RT`INMZSG%NYPl|WPmF{D& z4!|^ghe<5DG62Gad~_qS(nMo(YvO;~F~iYX=*=&0(AM!V_laMwpC$hoke0+%I7oh6 z>r(9bm1SI*tTMkm6x2bG#X zeSLMLG6|YxS}c9v>Ys)C^6G`B=zPbbbG!IhtIAo0`4Y0QN;@3Jh=AN&;H z+7?;QiFht_?cAYF)#$O}f50PVvLw z5DB%o&aqs&YYR=A)^H!zoi3!E>rL)8!BCfC_gOa66QsQ(rw?zW=N!B-9I9igZk6KL z6dCsJS4*HyW>8B*{uUg%f^*ht0Uz2HRfnu@X_1b45q=-V7%m8SmXxQm&M(KC=I6&}e#dV0@sAxw4* zDjUvr(HFJTe71(7@etI;POqJjpaZ)z=O-iB%kND{-~dHsw!HAPxFX8+)w3fZK{vrX zNA&AYXhYcq-NK1W3`)*}q|v*yId$cxt9lvKt=rWtz$usN2_UI1cG8k1ssJlu|GAEy zvwZNj6kuJxtRU4d)J%Luo+PFTk3+b)vP3X}WP^(-V z`S;r$-pvryu@4N}bUqpckJYe_>||OS=nzvVzFqJT^688760zw}%EB%Zd-cekas9?h z@%*mk>WpI?MLFauPN>Mcu!x+Bo{vrBT(#Nlm2{{@LUZK@Tri%_D@?B4zU?mJuAGRt zssEwdM`;qx!u0|!I-F8sOT;l&4VS=ketkne$0>t>Gsljz>ommaQs3UxVL<;o`~&w= z>Xdm~knt+Zq`TdNqVSb*(E^e)Pehcxl%g8^`WUV2BP0Hfr7zj1_0g4~{#N|rE;MN@ zV!r6X$iJSQ;K<&kIo6V_unFHEv-g^0s|OC-kW?W<8m!&EWn0Em;&9uH1>WG6OEn7e zQcl%9Dv`IRtA?z0HePu2Xq5go);XN8nTsnLstmA*b5qnenF&5yI+_~f=&qa?iO zeG?RbUMS-_Twm}ki-m;t+UR%NZCFd*Uo?5+(U1sK{kp|+btPLmF2827%Q^|47T}Td za5%kAZOzDjjwt(`2&5tbapu4!DD+G?pp^}hd}HE zZeN*sPWWo~j9pUdz4ZO9=Z8$!doIK5J4lpB-Q06s__@Z=0FQTKBu8O;xhB_IYFo84 zut#@f`@5o-6vVLwj|byOrEokt$n}fYt3)`huKTzXVm641Nvx05N%QSyj1ZVdO~nPM zGi%~axaCmE7~^b3h=f&n`bSI#DqV(2^(2Cq9u|&_Nokd1(`(!j6t9oUgFhqH`F%8!2nEjNw?x~~o%^I|CFu}e z#faY2BjEH{BYa!AC8lz2W6|M5(z=ku`?lJsCmYVzB|F!k+E8+Q;EsXyg+6wqPQ&Z< ze!=ezm?BTdUTUPoiqCi;C8bBFa;D>SGZOOMi;ymB4O2f`yzt8fA#<5(0uIUW2$&k! z7ZpUE7jZoH%9Jb%FVkWl_PMqsbGlAloU&DuEkZJYXiceLZa2?#^~lBCZ>MW|AP7}l zmEo8+JrW=_Y-PBQNQCu;*Kw-Ll->9cb$mPD7b)$};QzVNSC`@K;uJ2b={m`JqT{gL z{j#}<_TnR4eLxn!GB;|-#Oe~`Y@qiM9T~*jM%%6N_$e)ZI{nw01g#Re`eDbY(4jg9Z70 zfn0qOYVDZrJY^TnsAdy9*BPE$jf+{B4oJkmvg;T2A^XwfeZ$!L-bQl01YFYOtX>!| z=DQY}PSE#}PCH!}*qgijaWiJ)uZsOMRIaouvK2VgMke@sG@Kp*!Jg)Ocnp{1<}pUd zzke43-HF7;DSJX#e63tX{18|&lR`p>dIP`z!{pPHo|IC zJOK_f&Op5LS6tJIz6Kwt*+_^arp$VM@g%vOu>QW>tqbaXir_}F6|PAU_s+e45eao+ zr2E2-=7fQ!v+L@esE<6Jmdo30Ws&|uF>6{kS|{HwCs<^cSA?{tZMqGPK&w0`IJkmaN$Y}EeH;=mfgO(nFeqY55nWHPeX?-SyccN$SE_cX2pgmb`}3rkTnw6I}Cx8)x8 z8WV3!*-fC~Yg0+Mry`(5BrvVx?(h{W)xj_!@)#OTfux$z`Y?%=D@sE?=at%9~!Fce~FGz_6|mhDS2ABhAUq*2F*PlEG9Q`^zsOJyEZ{; z_S1cFh*|xi*VHt6!bJAmaR9eI;cernGXRvfgvTZ3%#7nZc4e4^ca%E#lW~qVnOe6C zu!`rO@*Ur-lRhQMQ@t*pJPnRY;`J6N=*_bftOQ@NilgoD(#|6WNU4h#{kmOM{bkl5x8m8QpE9=X!2iEzWmC; zo#u$u5P8zV$AqKr+dInX`Eu^sak4|{;HX;fO(P9xsCr4PhD^uZoRo78KxpZhq^*-Z z#2QuL_f~8|G^u-T=;|I7@&@>Xu7~VcOG){jlZ3A)b9;lbJ7eB@>8mU%sfdYy#PjhT z8bFyBrZ97yeW`TB|Fo+L2o5+8B<`oSfwXMxZ-^#!>o?nnvX)JgzhPLXno_0p0lXTH zd!s~@zHCAmZb$@5_$W(ll121Wo7=}N+G|>xx`S>P7{=o!6Gzoz)SGZCRY}u3JA3#4 zw#HNQWKnrdQ@gYB8H`_+6C|$YrW~4bofQooNWq(Ox8+@y9i>^Xp?sa1X-LMGCu)n} z)^JRtmXt~#R1$R< z&9kHC?3ccEDjM^Js+uz;tNc+NI{Hm%vd$Oesy}sqKca?%O0u)BYA4(X;HDG^9JL%I zRG*Mha2zWqt$s`lr8RA2JroegWA{6IPvsvSK~S{NNukSlqxP{O&*q5!=2#+Cfi)~W zJfTJVT%pkr-}Ugm3qLEvXIX0q_`E*-7>xZurwB3yPLMNH?sc}0hwZD~}o$&kVRNh^X; ziTLjcw25_K^N;7+WOFx!szycf@o`<-!Ioww2^u!mP^d^D-%!YPcF0$Bfg7+pmW$`y*^ts>{n@BeAxv4?d_eJ{i){&cNQ2v<+rVJ#LDi)^1p6-U#lrqWT|LI9N5^-96=7Vg(31iM77PF)qbIJ1h!<@#E=j)4t)m}_G5 zRIITCv|tJ?ZXH{Gu6pvUwYZ@%)pM5~v*G~_^uA!Tdo`lQg$5>cP83oU+T`24%U zwNZZI-)QX@4xq+)MUCxG&8N_by(t%z^C-8NZ6l!?4NZDv%Ecns?{zyl5yK}aRPoVl zPP;DlTu5Y3=#q11=Tz+9-JX*Cper4N{L}+$@WzSRs~e|@65xn!$@%2_ET{Li)7bX! zb62EbpB-hM>8>SKmdm}Mnz|Ti7rWt?^?y>c-IrL^&FbHiJO+Vz(1JOXdfSe7-hEcj zG9P=m6DuQUhhI-k(lZ~9Zh}6CvSi$IlD|()f8^)2QJicnJbh(M$(Rvij#W%mwF%7= zWp3PE`ulBneYnvc(Q%{ZgDZHVQ1`-qiz7qkR`@x1!m+*s5V(Lo}i5op=k8uy-Tm zeZ{AZ&uN%&#&11ht(sH34+PRFw91T+HlxH^0pyRKa3XUJbH!d+Bhc>Yz~yN?sCgpc zaE(7%WX4ox)e`S#K?f*Y`jpi;b}Lp~?n_Fek_yDt8!HsdhS=GN_pJ~VR^g4ePPZRw z33rg1hwwz8R*??iHy7+i*x7BxLLkFYshLW_R(FPgOI9TExkeuR2}3TQ3Ej3a<7jH# zrjA9xn?_QdM!@LsHrAMN55LRIX07w)MH9+_wn~iouJZPHG*?|<_OFAuZLaZ>S%-bM zJ1+Wdt#BTVex1ke6*h9wj)4&}1Un4PipC>R@KiZiWbSSr_4ka(sksf3^ z9r+j}YRALjqbx;IE!WlOv3cUr!5*6T?FgjY6NWm}X@AD&lzEymzy^7jT$oS@`08vH27^SL4gT{-8~88hlJ+)=gAZtBy7%?5O>4AM{+zl zX0e-tT5xu*w=BA>iaU(=;_Kvv=AI1_DSa3{mmneoa7CbW7*OM>adBPGa4VPPQE|Jd zW#mi8Ju$S&+a`_~V(dj*h65n(k;CX@OJmClP(me4ZLqchEMX;b zoA*KaTG2Fa*nI}~m-L=<*tc4K_7m`SRyUG9)Ts3YiBM^&iiSDfP2wvsU#5(S`id0M zTaxo7qZnIau|A)#aSHi?ZU^b78nM<$(au~?Cw02GCD%0xi-c0ova)R?B!fmVl+omb z2Y}UNEVbU)A1F%e!F>a3dBXTQijhop3`bwlFHU9gxT=w&vUAug*wo8$ z=X)r(6@EZ>@)aQg?+h?+DRK{V3UX_>L|&Ud^f-IEVTFU38j2N&e#p#j%%AFmXp`1h zVvxlfknF{cbkjPmYq7!_)M6hOvfyh;gQ^wO+V^*8O6bij8kLQs<=h=JWoTNjVH7Tn zjek&npkObvAd@~JIU(gMShGgcEF17M4IZSMN@HsjZlSSK9(u62IM#BTzf=^k+m~6V zxQ-u`c)eW=I7l;++SE?0>swL2V_ZDOhgDp=l$B!1SIYJ@XXDhZ@Krm&wJmT_t*117gH_{ zcU{SCVedByY82(Ubh>OFwfj>$o;jUy;Qh#6mih*~i@uQ&IR&vc^Pjpmd4}hFZ855K zD4D4-_wa5iNVt7q@KE2By|tp=w#?=gk%J&RJJEEA!<{{P#N8?Oqs-Am7=KY>CMvgj zD7F8O_a(OIpbL*HE6=`_UtKkDgm8CD&ppfFA*b6ZPpi;H>B2Lp@#^a_MShN+In8e0 zPqo=Q3OJDyYm5bK#6Ud)z<+yRUAd$U2ycJ_P zAdbah;)D@z^jtIr1+uBdpp6juuz0cdqA5R6uDrmo6rj>X@ddJjp*Rfdqy1H#oWHfD zQk;v6JCuo^=T+jm{Dcu3uD@xq~2DT=%;R#xgjpnDV(TI82yOws0m+kckpL zxB@4Jx}I{mZFUU_X=^*{A6nSW|Mc*)p&t|&0ZNfqsD7G791>Q@NzO4Oya{2kr8w=> zMl__oDbj9f=nGXE@m>4_9^7-k;|ORB#uFTqoOxg(%KreW807K!^GRFtE8iBNa%EFj z>_DFVDiu&n- zOlu(;yFJ8`K@^~}WGxAH=U)@5O!>k=@P22nYM6jyT7fi_N)uv^b*+=FV;)Ah2K-x|kHI-7NTRX!GEOP1g)ru6#;k)O!!?U!nej%<6 zZN@RxDlrKkL?`%Y#IiYFlZ*yvaYyz~81qr`5Bt(6hj)&7ABMLN=H_wdZH6&+i6L$$ z;mJu~*gy<>7`!}so6o>IV6u%-Vh4aGu?BAR0eMGUITeNsf*@PchrW#aL`q}WT)%wjKD+>x`avEDtW zlt!ON78F~O#*+{@+q{xf?7fn9W>K;0>}7J>T|cuElG*~RyfXnu{~V_#9xG+reeud3 zUe9HAM!?8YQ*>;hI8Bp8Kk_EJd?6_UXWyV&Xk7G|;szefH}UtdsgPPlpX^O}ZO*UF z>&L}eMIMs4wDNxxiAJm6HGEN<$(~UCUu0`!po^Tt-J)*%fL{zabSC}^-~AU18w|Dp literal 0 HcmV?d00001 From c18cbef8ff879f3e9b096d11aa2c93b3415f07fa Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Mon, 19 Aug 2024 16:13:09 +0200 Subject: [PATCH 3/6] add comment about sponsoring validators for bootstrapping Co-Authored-By: Eric Mastro --- evaluations/sidechains.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/evaluations/sidechains.md b/evaluations/sidechains.md index ba87d89..bee29eb 100644 --- a/evaluations/sidechains.md +++ b/evaluations/sidechains.md @@ -168,7 +168,10 @@ the gas price will go up. For the short term it seems viable to start with a dedicated side chain for Codex, while there is no high demand yet. This gives us time to work on reducing -the number of transactions, for instance by aggregating storage proofs. +the number of transactions, for instance by aggregating storage proofs. In the +beginning the number of transactions won't be sufficient to cover the costs of +running validators, so some sponsoring of validators will be required to +bootstrap the chain. For the medium term we can consider to have multiple side chains depending on demand. If demand is reaching capacity of the existing side chain(s) then From 6b2d7a411ffc0e741fecbc5f8ebd2a9b7de60551 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Tue, 27 Aug 2024 17:31:08 +0200 Subject: [PATCH 4/6] Draft design for a storage proof network --- design/proof-network.md | 245 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 design/proof-network.md diff --git a/design/proof-network.md b/design/proof-network.md new file mode 100644 index 0000000..b1509c6 --- /dev/null +++ b/design/proof-network.md @@ -0,0 +1,245 @@ +Storage proof network +===================== + +Authors: Codex Team + +In this document we explore a design for an off-chain network for validating +[storage proofs][1]. Instead of checking each storage proof in a smart contract +on-chain, we let the proof network check these proofs. Only when a proof is +missing we go on-chain to enact slashing. The main goal of this exercise is to +reduce the costs of submitting and validating proofs, which has shown to be a +limiting factor for the profitability of storage providers and the scaling of +the storage network, even when deploying on a [rollup][2] or [sidechain][3]. + +[1]: proof-erasure-coding.md +[2]: ../evaluations/rollups.md +[3]: ../evaluations/sidechains.md + +Overview +-------- + +The main idea is that validators in the network sign off on messages containing +correct storage proofs, and on messages that correctly indicate that a proof is +missing. These validators deposit a stake on-chain. We consider a message to be +validated by the network when a subset of the validators representing > 2/3 of +the total network stake have signed off on it. The assumption here is that less +than 1/3 of the validators are byzantine, meaning that the rest is online and +following protocol. + +Roles in the network are: + +- provers: they are the storage providers that submit storage proofs +- validators: they sign off on submitted proofs and missed proofs +- watchers: they monitor for missing proofs, and trigger slashing on-chain + +They are all connected to the same peer-to-peer gossipsub network in which they +exchange messsages. The provers and watchers also monitor the on-chain +marketplace to check when storage proofs are required. + + + prover validator + + prover <---------> gossipsub <--------------> validator + + prover ^ | validator + \ | + \ | + \ v watcher + \ + \ watcher + \ + \ ^ watcher + \ | + \ | + \ | + \ v + + marketplace + (on-chain) + +Messages +-------- + +The messages that are exchanged over the gossipsub network are: + +- `SubmitProof(slot id, period, inputs, proof)` +- `ProofSigned(slot id, period, inputs, signature)` +- `ProofValidated(slot id, period, inputs, combined signature)` +- `SubmitMissed(slot id, period, inputs)` +- `MissedSigned(slot id, period, inputs, signature)` + +A *slot id* parameters refers to a [slot in a storage request][4] on the +marketplace. It uniquely identifies the data for which a storage proof is +required. The *period* refers to a [time interval][5] in which the storage proof +should be submitted. By *proof* we mean a [zero-knowledge proof][5], and by +*inputs* we mean its public inputs. A *signature* is a BLS validator signature, +and a *combined signature* is a BLS signature that is a combination of multiple +validator signatures. + +#### SubmitProof #### + +A prover broadcasts a `SubmitProof` message to indicate to the network that it +calculated a storage proof as required by the marketplace. + +#### ProofSigned #### + +A validator broadcasts a `ProofSigned` message in response to a `SubmitProof` +message. It only responds with `ProofSigned` after verifying the correctness of +the zero knowledge *proof* w.r.t. its public *inputs*, and checking that the +time *period* has not ended yet. + +#### ProofValidated #### + +A prover broadcasts `ProofValidated` after it collected enough `ProofSigned` +messages from the validators. It combines the BLS *signatures* that it received +into a single *combined signature* which represents > 2/3 stake of the network. + +#### SubmitMissed #### + +A watcher broadcasts a `SubmitMissed` when it notices that a required proof was +not submitted. + +#### MissedSigned #### + +A validator broadcasts `MissedSigned` only when the *period* has ended, and the +validator did not previously broadcast a `ProofSigned` for the same *slot id*, +*period* and *inputs*. + +[4]: marketplace.md +[5]: https://github.com/codex-storage/codex-storage-proofs-circuits#circuit + +Flows +------- + +### Successfull proof submission and validation ### + +Provers monitor the on-chain marketplace to check in which periods they need to +provide a storage proof. When a proof is required in the current *period*, the +prover gathers public *inputs* for the slot, including the random challenge for +the current period and calculates a zero-knowledge storage *proof*. The prover +then broadcast `SubmitProof(slot id, period, inputs, proof)`: + + validator + SubmitProof + prover ---------------------------------------> validator + + validator + +Upon receiving a `SubmitProof` message a validator checks that the *period* +hasn't ended yet and that the *proof* is correct w.r.t. to the *inputs*. If that +is all in order it will sign and broadcast a `ProofSigned(slot id, period, +inputs, signature)` message: + + + validator + ProofSigned + prover <--------------------------------------- validator + + validator + +Provers listen for these `ProofSigned` messages from the validators, and once +they accumulated enough *signature*s from validators to represent > 2/3 stake, +they create a *combined signature* and broadcast `ProofValidated(slot id, +period, inputs, combined signature)`: + + ProofValidated + prover ------------------. + | + | + v watcher + + watcher + + watcher + +### Missing proofs ### + +Watchers monitor the on-chain marketplace to check which slots require a storage +proof to be submitted and what the public *inputs* for the proof are. For each +required proof they then monitor the gossipsub network for `ProofValidated` +messages. If they do not observe a `ProofValidated` message that is signed by > +2/3 stake before the end of the period with the expected *slot id*, *period* and +*inputs* parameters, then they will broadcast a `SubmitMissed(slot id, period, +inputs)` message. + + validator + + .--------------------> validator + | + | validator + | + SubmitMissed | + | + + watcher + +Upon receiving a `SubmitMissed(slot id, period, inputs)` message a validator +checks that the *period* has ended and that it hasn't already sent out a +`ProofSigned` message for the *slot id*, *period* and *inputs*. If it indeed +did not, then it will sign and broadcast a `MissedSigned(slot id, period, +inputs, signature)`. + + validator + MissedSigned + .--------------------- validator + | + | validator + | + | + v + + watcher + +When the watcher receives enough *signature*s to represent > 2/3 stake it can +combine these signatures into a single *combined signature*. The watcher can +then submit *slot id*, *period*, *inputs* and *combined signature* to the +marketplace. + +The marketplace will then verify the correctness of *inputs* for the *slot id* +and *period*, and checks that the *combined signature* is representative for > +2/3 stake. If these conditions are met, it will then slash the storage provider +collateral and reward the watcher. + +### Faulty proofs ### + +The storage proofs that a prover submits can be faulty for a number of reasons: + +1. The zero knowledge *proof* is incorrect +2. The submitted *period* is not the current time period +3. The public *inputs* to the proof do not match the values from the on-chain + marketplace + +Faults 1 and 2 are caught by the validators. Correct validators will not sign +off on invalid zero-knowledge *proofs*, or on a *period* that is not the current +time period. This means that it is not possible to construct a `ProofValidated` +message with a *combined signature* representing > 2/3 stake. Watchers and +Validators are now free to treat the proof as missing, and go through the same +flow that we described in the previous section. + +Fault 3 is caught by the watchers and the on-chain marketplace. Watchers will +look for a `ProofValidated` that has the same *inputs* as specified by the +marketplace. If it doesn't find it because the prover broadcast a +`ProofValidated` with a different value for *inputs*, then it will treat the proof as missing, and go through the same flow as in the previous section. + +Consensus +--------- + +The core of our design consists of the fact that correct validators either sign +off on a `ProofSigned` message -or- on a `MissedSigned` message, but never on +both. We then use a light form of consensus by combining signatures of +validators representing > 2/3 stake. Because we assume that there are < 1/3 +stake byzantine validators, it is always possible to either get enough +signatures to validate a correct proof that was submitted on time, or get enough +signatures to sign off on a missed or faulty proof. + +There is one scenario in which consensus might not be reached. When a proof is +submitted at the end of its time period, and it reached some of the correct +validators before the period ends, and some of the correct validators after the +period ends. In this scenario it can occur that it's not possible to get enough +signatures to validate the proof, and not enough signatures to sign off on a +missed proof. + +We argue that is not a problematic scenario for our storage proof network. The +prover did provide a correct proof to at least one correct validator, meaning +that is still storing the data that it is supposed to. Not being able to slash +it in this case is therefore ok. From c6fae1342a481e8b4b2433c4fd5094bc27b1203d Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 29 Aug 2024 11:20:55 +0200 Subject: [PATCH 5/6] rewording --- design/proof-network.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/design/proof-network.md b/design/proof-network.md index b1509c6..6140133 100644 --- a/design/proof-network.md +++ b/design/proof-network.md @@ -114,10 +114,10 @@ Flows ### Successfull proof submission and validation ### Provers monitor the on-chain marketplace to check in which periods they need to -provide a storage proof. When a proof is required in the current *period*, the -prover gathers public *inputs* for the slot, including the random challenge for -the current period and calculates a zero-knowledge storage *proof*. The prover -then broadcast `SubmitProof(slot id, period, inputs, proof)`: +provide a storage proof. When a prover sees that a proof is required for a slot +in the current *period*, it gathers public *inputs* for the slot, including the +random challenge and calculates a zero-knowledge storage *proof*. The prover +then broadcasts `SubmitProof(slot id, period, inputs, proof)`: validator SubmitProof @@ -225,7 +225,7 @@ Consensus --------- The core of our design consists of the fact that correct validators either sign -off on a `ProofSigned` message -or- on a `MissedSigned` message, but never on +off on a `ProofSigned` message or on a `MissedSigned` message, but never on both. We then use a light form of consensus by combining signatures of validators representing > 2/3 stake. Because we assume that there are < 1/3 stake byzantine validators, it is always possible to either get enough @@ -241,5 +241,5 @@ missed proof. We argue that is not a problematic scenario for our storage proof network. The prover did provide a correct proof to at least one correct validator, meaning -that is still storing the data that it is supposed to. Not being able to slash -it in this case is therefore ok. +that it is still storing the data that it is supposed to. Not being able to +slash the prover in this case is therefore ok. From 7bf8f0c6b1988aa38857b00c3f6b10744bb86b4f Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 29 Aug 2024 11:22:05 +0200 Subject: [PATCH 6/6] add sections on "staking" and "pros and cons" --- design/proof-network.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/design/proof-network.md b/design/proof-network.md index 6140133..f3e3c55 100644 --- a/design/proof-network.md +++ b/design/proof-network.md @@ -243,3 +243,43 @@ We argue that is not a problematic scenario for our storage proof network. The prover did provide a correct proof to at least one correct validator, meaning that it is still storing the data that it is supposed to. Not being able to slash the prover in this case is therefore ok. + +Staking +------- + +It can be expensive to calculate the amount of stake associated with a combined +BLS signature on-chain. Because any combination that represents > 2/3 stake is +valid, there can be many different valid combinations. If we have to calculate +the amount of stake every time that a watcher submits a combined signature that +signals that a proof was missed, then the gas fees would be prohibitive. + +So instead we expect there to be pre-calculated combined public keys that +represent > 2/3 stake majorities. The gas costs for validating the stake that +these combined public keys represent can be borne by the validators when they +put down their stake. + +The tokens that validators deposit as stake can be used to keep them honest. +Should a validator sign off on an invalid proof, then the invalid proof and the +signature can be used to prove on-chain that the validator misbehaved. Their +stake, or a part thereof, can then be burned as a disincentive for misbehaving. + +Pros and cons +------------- + +There are a couple of advantages to using a very light form of consensus. The +validators do not need to communicate amongst themselves, so we can forego the +three rounds of communication inherent to Byzantine Fault Tolerant consensus +algorithms. This leads to less communication overhead and lower latency. + +Our design also allows validators to operate nearly stateless. They only need to +keep track of which proofs they themselves signed off on for the current period +and one or two previous periods, depending on how much time we want to allow for +watchers to notice missing proofs and submit `MissedSigned` messages. + +In exchange for these advantages we have a drawback as well. The number of +validators is by necessity fairly small (in the order of < 100 validators) +because each prover needs to send messages to and receive responses from about +2/3 of the validators. Measures can be taken to increase the decentralization of +the validators. We could for example introduce epochs in which some validators +are chosen from a larger set of potential validators, but that comes at the +expense of added complexity.