From 4cace7ff698b621dee19f7b6d838a7f7651b3e1e Mon Sep 17 00:00:00 2001 From: Shanin Roman Date: Fri, 29 Mar 2024 12:46:38 +0300 Subject: [PATCH] [fix] #4267: Introduce p2p idle timeout Signed-off-by: Shanin Roman --- Cargo.lock | 1 + cli/src/lib.rs | 9 +-- config/src/parameters/actual.rs | 13 +++- config/src/parameters/defaults.rs | 2 + config/src/parameters/user.rs | 28 ++++++-- config/src/parameters/user/boilerplate.rs | 5 ++ configs/peer.template.toml | 1 + configs/swarm/executor.wasm | Bin 546991 -> 547010 bytes core/test_network/src/lib.rs | 8 ++- p2p/Cargo.toml | 1 + p2p/src/network.rs | 17 ++++- p2p/src/peer.rs | 78 +++++++++++++++++++--- p2p/tests/integration/p2p.rs | 34 +++++++--- 13 files changed, 159 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06fa8f6a1f3..b09ce7122a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3122,6 +3122,7 @@ dependencies = [ "derive_more", "displaydoc", "futures", + "iroha_config", "iroha_config_base", "iroha_crypto", "iroha_data_model", diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 9854535d50a..0787ea2207c 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -203,12 +203,9 @@ impl Iroha { genesis: Option, logger: LoggerHandle, ) -> Result { - let network = IrohaNetwork::start( - config.common.p2p_address.clone(), - config.common.key_pair.clone(), - ) - .await - .wrap_err("Unable to start P2P-network")?; + let network = IrohaNetwork::start(config.common.key_pair.clone(), config.network.clone()) + .await + .wrap_err("Unable to start P2P-network")?; let (events_sender, _) = broadcast::channel(10000); let world = World::with( diff --git a/config/src/parameters/actual.rs b/config/src/parameters/actual.rs index 6b10b3d870b..c9dc0973ab6 100644 --- a/config/src/parameters/actual.rs +++ b/config/src/parameters/actual.rs @@ -31,6 +31,7 @@ use crate::{ #[allow(missing_docs)] pub struct Root { pub common: Common, + pub network: Network, pub genesis: Genesis, pub torii: Torii, pub kura: Kura, @@ -71,16 +72,24 @@ impl Root { pub struct Common { pub chain_id: ChainId, pub key_pair: KeyPair, - pub p2p_address: SocketAddr, + pub peer_id: PeerId, } impl Common { /// Construct an id of this peer pub fn peer_id(&self) -> PeerId { - PeerId::new(self.p2p_address.clone(), self.key_pair.public_key().clone()) + self.peer_id.clone() } } +/// Network options +#[allow(missing_docs)] +#[derive(Debug, Clone)] +pub struct Network { + pub address: SocketAddr, + pub idle_timeout: Duration, +} + /// Parsed genesis configuration #[derive(Debug, Clone)] pub enum Genesis { diff --git a/config/src/parameters/defaults.rs b/config/src/parameters/defaults.rs index d81c08b4ac9..4b42ac46c90 100644 --- a/config/src/parameters/defaults.rs +++ b/config/src/parameters/defaults.rs @@ -33,6 +33,8 @@ pub mod network { pub const DEFAULT_MAX_TRANSACTIONS_PER_GOSSIP: NonZeroU32 = nonzero!(500u32); pub const DEFAULT_MAX_BLOCKS_PER_GOSSIP: NonZeroU32 = nonzero!(4u32); + + pub const DEFAULT_IDLE_TIMEOUT: Duration = Duration::from_secs(60); } pub mod snapshot { diff --git a/config/src/parameters/user.rs b/config/src/parameters/user.rs index 5afae534472..35774e882a6 100644 --- a/config/src/parameters/user.rs +++ b/config/src/parameters/user.rs @@ -186,7 +186,7 @@ impl Root { } } - let (p2p_address, block_sync, transaction_gossiper) = self.network.parse(); + let (network, block_sync, transaction_gossiper) = self.network.parse(); let logger = self.logger; let queue = self.queue; @@ -216,7 +216,7 @@ impl Root { let chain_wide = self.chain_wide.parse(); - if p2p_address == torii.address { + if network.address == torii.address { emitter.emit(eyre!( "`iroha.p2p_address` and `torii.address` should not be the same" )) @@ -224,10 +224,13 @@ impl Root { emitter.finish()?; + let key_pair = key_pair.unwrap(); + let peer_id = PeerId::new(network.address.clone(), key_pair.public_key().clone()); + let peer = actual::Common { chain_id: self.chain_id, - key_pair: key_pair.unwrap(), - p2p_address, + key_pair, + peer_id, }; let telemetry = telemetry.unwrap(); let genesis = genesis.unwrap(); @@ -239,6 +242,7 @@ impl Root { Ok(actual::Root { common: peer, + network, genesis, torii, kura, @@ -457,20 +461,32 @@ pub struct Network { pub block_gossip_period: Duration, pub transaction_gossip_max_size: NonZeroU32, pub transaction_gossip_period: Duration, + /// Duration of time after which connection with peer is terminated if peer is idle + pub idle_timeout: Duration, } impl Network { - fn parse(self) -> (SocketAddr, actual::BlockSync, actual::TransactionGossiper) { + fn parse( + self, + ) -> ( + actual::Network, + actual::BlockSync, + actual::TransactionGossiper, + ) { let Self { address, block_gossip_max_size, block_gossip_period, transaction_gossip_max_size, transaction_gossip_period, + idle_timeout, } = self; ( - address, + actual::Network { + address, + idle_timeout, + }, actual::BlockSync { gossip_period: block_gossip_period, gossip_max_size: block_gossip_max_size, diff --git a/config/src/parameters/user/boilerplate.rs b/config/src/parameters/user/boilerplate.rs index b2863772d71..07ef9aa4a16 100644 --- a/config/src/parameters/user/boilerplate.rs +++ b/config/src/parameters/user/boilerplate.rs @@ -417,6 +417,7 @@ pub struct NetworkPartial { pub block_gossip_period: UserField, pub transaction_gossip_max_size: UserField, pub transaction_gossip_period: UserField, + pub idle_timeout: UserField, } impl UnwrapPartial for NetworkPartial { @@ -445,6 +446,10 @@ impl UnwrapPartial for NetworkPartial { .block_gossip_max_size .get() .unwrap_or(DEFAULT_MAX_BLOCKS_PER_GOSSIP), + idle_timeout: self + .idle_timeout + .map(HumanDuration::get) + .unwrap_or(DEFAULT_IDLE_TIMEOUT), }) } } diff --git a/configs/peer.template.toml b/configs/peer.template.toml index 2c8b88a7616..cce2aab5990 100644 --- a/configs/peer.template.toml +++ b/configs/peer.template.toml @@ -24,6 +24,7 @@ # block_gossip_max_size = 4 # transaction_gossip_period = "1s" # transaction_gossip_max_size = 500 +# idle_timeout = "60s" [torii] # address = diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index 1abb8d63df422c8052fa4b13140f309cc41dc100..46579c359dfbaabb97fbfab8e19079a4d469b746 100644 GIT binary patch delta 63509 zcmd?ScVHAp(l@-_)3dwEBa|a6fk0%D4Gw5!gChqx;cVk<;lsx9?i?g?2H^$TWH4Y1 zCWyFXL^9DJas~k=7z9WdlMU~$dUjU<+3-C7eBb%u&YGF->gww1>guZMurp^Rt(=vV z8>P7-wU=BUYyWYb)2c9wD^!edEfNh}XGB;Q=Yo6w`Eku+(JdB>)uLIL#uy$NzL}<3 zZS-le_#so*0cNvsd^4^ggWl*L;80vc61Ol5x1hL1V^(|+DtZ7PisD1(Iuh|6jkd$Fjq&Y4*&lA@(Ls``XvB??f)&qV3Q&YvXuN(M_xn zBlOYw82wv)xIT*itoO6-;p_aT^1=2Ke5`$({Ww3&&)Y`oEB&VMuKp)^AwS29`LBE; zciHE#wQL6afnQ|5vkPn@pTwu~Df~x1f$!x<`7ypro5;so$LWQ(-?R8R+XDMM`|s>q z`vv}ueUklq`(*nM_R;o{_7Qfe54SI}jZU4=l?RUgJ$1m6Kqq0*FMw!qkXD< zy}y6Y{5cQ!|HnV|8$F2y#soOHQ)C)PZTN`BM-48FiS!ZW{csh8M`bDC2oLaP$`3a` zYH$lM1ZLuCD4;NJIRdKmCqSWpl5UhP9AW|)Cu~UpEHK#fwb|7rBFZE_(35nGstWLY zsFwKSL$$<}7ZDYs=(3ynW$1MkMI^RXxw@zHMnWY#AHUFt=0!yxyz~b%!OCKMF>*`8 z-6F7BfJ1XO%1mZXZcJv1#|~y(6M-qd46RhgA=k@M(Xod_U=?4sUMhRHYfw~!CkjPi zWnZ>m>1+|0=*#dgl>vkazKnoU8M|FU(b2J>GtQSCR4V(Bs|B)e3K9=bGeSyb7rHt} zM>j%g$cQI9v{d$W5g6&qs8lNBns6ka!A4l*-@jx*pwv^>*DGlfrhpI>bcB z_SUIiJ)j9?KwU8n;?9adn=d=5RQ3(wDu{_-xUtWr#oc1FU0QrH+c2kE{5mcE zCl&|+3N~`AN_HH!CS1v;Bhy&u@^^fgwbZWUNM%46vh_@3jS?T$+=3Qxr#;hHWOryu z!r>><9h$@6;qOfEY%I1Xi<>J_z7N?@{j7{+Ru+l(c< z0#Z7%-g7=r**@Uu?KT?545X(*UF@(029UhsrvPNS}a~i5xzAX^L z+Y7kWHD*p4o9NmyCsur;2L`*Gi=*n|r4;7Pr7@G9nphgSvC-9FZd&4Q8#v@(kO5`)=?X&O>Y{$N|ioVrt~kaiSv>|PLzQ->Dn%;l+;smsSYwO||aZ&`vy3XO{6b8O4U`dSlRRl)6*n${#+Qr=Q zA!pRU_EKizdB{z8`nuxKxZ_!&>n8pla>Xr(55a)Nyy3;LSyA%J zg4XPuYubVsaUQv@0qz)41Pwu`LW)J{cI*axJHWoSFrGj{y&$C+x=*3ZTi8lm5P=3E zkU@Di*Tazz9N5kvS@;cBrs zhJT~GLKa53IxlX4HqKfc&!O42ERLf`As*L-%Wp|s$PH0iP>-vM9$(T-{DE}UOek1C z)rMOl5Yv;FEhgmgCC&IB!sS>RCje(7xG2C`Nn7MwGD+A(GBY;XoXoX#Nw}-q(kOP; zHF9Z!*y2sfM^d)yROzIIWt7x-Svz*d)oa<~eqD4Dd+xmAx_?=97hj&t&dfuBtu*#^8v9xetq9sDm0!`3fU%F)Y$zmX$xbUsOZHl^CCJo+nsc0%X>4}Av2rRy z7q4o^*0^3<6(b*P$ipWLSjC_X2CjaRu|BRNYl?z~_&GS59+;VIGy2P{boM5@=sNgw zWwzb*$IsQQ{im(47~5o;leOl3Y%q)o5~H$fW`R4lqkt6!VU3jA8@i<^q-;q(Dgtq5i$Df^F4Z|J)SA zR=Ij@suO-xDAk$-V@pj_z<1QOZqtOIU6`}}f_+P--_E|m)&D2hHy*QC*X^B6N&eQB znXH?$7$iB{M&jGsX3k=G&7s#-u7n*V$xU|TlO$uLY0d?hEho(h+xa<*n4}W&ZJAXq z(Ak>v2V|{rjolR;)Wavj0wUaDHhY6z9F}KwK>CvMtf|(*AHAKBBtOivrty9@*`X6l zvtHapJt5ghHi$%cB&&fU?LJ^l@fduJRYl_Y71oFG_1Y*FiN`-yTB}2h$Bu#+53tGn zQLGUgEyvGe@37zHk)iCL!~V@|%;h?=FET_4v>xCUXnAOrHHK}FNn_Y!5afbkY*IKx z5>9}UVF4LdQ@LE>X5pwRbd8mUSFxLoh%n(W$w71p&_djjN6xXDkllLY*k@&Bch0PX z8#T7X_0^GQjn&Mn*I*s!#u?YKBMeL=8Dn<&@yY?4rV{VKOALu$kEiZmfhY?b)DLzR_pMzA4fSy-Nm zTvWQ^W^{a6+U(?Jcq>hnTccQ-fT}9pK78JxvYEG1*crtemL}VTv)5Vv&<-p*xNKEJ zdqFJ^Ry6VSj)_#FdPgJiFF7b*V<>w-Rl)Nus*Y5X`QJ)%TCczb}^N$?aIIL8k+iwwSuO`Qd1YmSvrgK&n3Yn3GZiCnOnNb z+&fp^-e$D!~CK>p|2L;f6y!c#rWEmJt}&V@Gyfx9!z!Uf*;W(TvFa)VP&4n{5WOu!0cVRLryRNdDv`rt_j)59JRTy3jeyY`O594^2;jDS5YF$?^1jmS=(?^xHDIWvE~}HDY98b_Oqb5AAtz^gK!2FFaRF_ z^Tt9(IE;*yx=e^+@9-hIERJC@a%>E%f?>HThSm0@t-$A;Sk@fc>|87?w%^@hajZS# z%a|w`au)jc5OLk6T zSs<}EiFGl}?saxDyR9AvG8gqAcw|R{=|JYu>nb@anZfRs^OD&m_LF;B6_&;#mSZew z&OAS_wLOkPX0o^{OGgC_Qdsk#d=xgBsezg2UL~trE*sBaIm#pBS#4{7)AyOVh_z*1 zhb?CJSg-6>_V$WuEC;Y#7At$ZxC44`yR7{>l;%a5Hv#7Hb~*NS7K6u%C9F2=?aryJ z0qZW4ma=ASnOr`Ry$i@CZ?L!EJPw@1Vk#+H+e)@JNfC_03$pc_u#Pv#>}Bi;nA`Qg zXYa99vff*)rWL??pe}RYgq^)s7JSdLk<(!^yC25%*vYIj`HadfrwJOk_DaVOtf~96 z+RWk4mdMlx*fw@eUVnhKlDSQp9Z8S1U^(tb??D4f$Ly5fUOHx{{B{U?9w*lm*vXYF z7qfFCW_LgHTccv#!uZL3sX42}_*~}pzmFwwPyH~s<&6heYqrFVx>H$DZ=VZPp%=gD zHa9eb{U31PWpFFjBWRqDHx;{w{b!bQ4|{mr!`$`%JNK}~YPg5J%DRV_$vyn!|8v*S zHS1t~nYEC`$~~>w<3auIz?x}3xhdy4_x^i&&L!-5_Zjwf&|#lq)}i9Me5v$KQ9eU( zOd4CE;x?JlvHH`kPxFB`SulmYYF)BJNlm-<%ndCy^J}P~?XqASLtspP_?%L5E3CW? zzCvw07LS?Rm6A()o;5%qL>fETOH9fY&$CJFlFYGl827TBACEP)oQfzQ8b#{}7l!R( ziBNKtcd<55av$ts7b&KINLqly*3zM=n1Tik-?j1U7z9AA|-*+xhqK&{{Ded(zCJB_D}Y3(C9m8lu;Ec+r|)$|8W@Z zze3Mu4}hm3KLKkN-+?vLd=gZmY>Pi-|0~w~|2#rjqGuI*s(;B^2Tkyq(|@9D`sjl8eTpOhwR$$z4Uw3~*mQT3LF|24zJBhBIjlDeI^a{k z6`OI>D%LD%@&lKedH#0lrTuW$A!z$wa-~MetW=^?)Y8YaElN!O$4vRJQ7nIqV{L=h z+-dw2nmVP#PO)bH_l}?Mf~MX{hi+1l1X)UlzKNOl?`o^2&t~C4@($DPrV6HAHAD*X z|JFk!Gw9r%M#qhE5uE$~OAYvTGH3<7-4SYUea)|Uk+sU57wF>Tm@BMf(B(T>ONFJaCF!_^b)5gwc<0bC{yD8=G3P1l zK1Z;b77$qtEgzefQu!Wi%%BBC+W$eXSjobxL5rcOJRG~v@rX87&)dN3Xh9c!?EjOf z&W#G9I_oz7ou^Rur$M|GXQ$*y+;9WH+h;Za%G9gnqF3pT;wuz>eq z51q3ppM?F8>NElN#bbl3di~i(2O!kzMjLI0r82bN9!D6wuUH%KyaqVYyB24b!x9G? z2nQD8Wgmk-7^;pS5u}HLiSnSqp90PGLwQE{dA0pmZ3EC8*ly=!#yQz5l(%Aqa&svE z2#d+iN_;cxC563{3?t)!gF-B`CibG5KA3PRRHvov%+}0 z>V=|I4puslbKFc)$8xBFNIL7T5zgOWRnM3QD+1|wf~tw0%>5Bci&3;2PM0$c#N^W+34>B)^K}PPR!dkHnhHY?&R!=dlH{ zNi;^qY}r1VKZzYWQ=@rxJhnyi8hG3=AJt;;wNSQ=;hBKM2KFY*Eic6IH=`EVlI_l0 ztg|zuRgl%eoqK3!xv@z8GnOv}XstN@BDR(FisMc3SWb_9@^T!nj7L;F9V$& z-^8Pe*>Xud&tMDPx8nI}=C=@Rr9IG#f6L6i&E)M>ZoYYC*%8F!ORbB^=b5(iexOhO+V-_cGgR>S&#_A}M2{-1;v6Xpi z@ZxM`-V*f;9HiG}^W3jH`27rfk;WxqovXmaRiJRW?a4fh@%c=SPvSA`h?#f9%6Fz7NUEgp>3D2S0m=)qFon-#%jKwQkhya*q&kle-Na}EIjvhkFrl5! zyYH*cM>F<~%&y6!WHEG8FiuFM)Ak0)BsY%At+kL*w+4?6#R0JgC?gsf>ZFR9*NO6Q zzT!U0bCk`SfxH;xHK)8(GY=hUH&5i5m0ki2+bu(C@>I6jMA@b$is3|ABPw=JMaAlc zg3Jb#o!+qwHM>!i9g;=#@U+TNi>u>gbqSnKClK}Jsdx`Sm4LH00g<4UZsJsAhM*ZW zDYJkwjT1y^y%3y!NTtM6D$zrJwc4n>P`03lhlUUE9s=}L3HXWvK4!LcI_2P0S~BHe zBW4NH&(!8I4lvz8Ilr(>XBc#WdCIOg!IkQRd+YERI!dMv)L};;7n&(T}?0d`cy-o7H z9VYE>f$n&=0iVRy%Nq@N6{DC11VGKGk^379z~<eB453a zKgOoIr{2e}GB#dLe1P8vJlIoT8HBJF(63u%ZF(G#?OX74#;UHRo6Itn)84k+%>EJ}^EbP)cB!5lk4KT6BJ0TwjWNRm139Lp2 zch>_}tz}UBZCG(~5sUisSztWvszi-2<<+{#F^$5|CTvLoHRiK4=Nudq5_%!c4bXe%K0XdaE4ViuXWb)Wb;pUS>Yb zYlV49Z;68f*uo1*TI~MeVg3t~KR(X=39``TS#G z)++h$$Dq)+%EB^<%^pYM0Xgk)-WHI5JWi1AgeSO_p%qnIb0<>YZmm*#wgytOw&H)N z+N^CFf0g|x7e32JnvcHnaC;t#xwW`Ga%RhR&+&)ZZ1?czV3;&q?o$~hL-?=9 z{9)-FtXIbl=2u?e>5=m>0-fQR=9Uq9BR#ZI&V2z|c)r~K0?fn3vgu80W7+;iK3ZF0 z50SyQtZ&JeUgGD_{KsFeU=%C2*4QmwFLQ~FfVE!XFY&P>WuI60%WS9n6i|G!- z3ELVq41K3avci~l3TK*uJ)_NE;~jW+s~r6r{~BgOdNH#Nu>QZ*# zDeS0wX$QWSHR)re!=yGx=))M1{z=$HgVs2O!{!v90600IC9E`@21bJRi4h!2Z!jP> zy}=u^MQ;8kKftgN_3&G~ffcBXo>m$4Hc#N)tnMana~p#}{J=XrCHPkzXWJkmb>tMs1zJR@$UrFc$aL@iC1M?WcyD1U)YkA--$mcHt5jsQ6KQC z)=gB`X6gKZC*pXc?C=51#F_Hb4={LV%84KFIVm(Lk+M% z$S*&{IM^yzeh8Yk$=^TZBk+~enK$%@azgoaEGS+keX7QGacABFL%jY+pliQ;mL6N> z7a#F@81O%Sr0^8e*FKr_F|S&JAY#}jJY2rPtru8p4p^Few2 zQ{J_HCcZsPm*a}FgFy)rd{~Mv1gX$6=C$ zDa-mF%sH~kl5u6i@WTgZtjfo|7BX}+Pqun$eXRRk*UI|H;_m!~=!&rVDuyN9`A41* zIpD&otphi$UpFo*W5kcUhR>P%dmn#qi!sTo7H{uy_jM07>#hiGN!>%tx({!@w)gVP zORL&vj2%Aw^oi~L&aJh0>xL1n>VBoyUDqum=kgb$D?(aQ^DfoRkxPEtyZhuhcfnpu z#^A2Q4~-bLGQWnm=6uxbkA6PY8#T`uHK=&e2s!VZ#Uo)owj3RDX8ge;t;$GPp^~t= z6``fNq5h4Xeo%s4Ck31<{3QAaLK?Kx`doV_b78GAOanmK#^VbL{;{8)%2CE*4nzw23;6-x6f!{0{#b^3$>wabUh@n|t#=t{T#Qf3k?uj|5 z7*nr8ynjl}0h2Rbe>gnp=$h|`F3-w1J?rqrfk*m`zUbwQ%o?E7K+gepPs>P?F%_cy zQ(8tS#zah+e);Dv@Z#mH1%N97CiY>;VyC-FgBBf3RSpSre(dL*L zx_tkFm77Mo>SnCpa$?top5M`KR8uwDe(+E-GUx6o8Lud*TM^nnC1spR%H;t&XH4(4 zcFeys=6utC-;6xhf=fP9#(|VD45F&v@bPar|h`kTqKh);^UnV(n4>foeHr2DIq;f zLN3kDS@i9IF5f+pab@IE*M{-Sa?-qnWP1qd_wC&iazZJTIu&63Q$miLI={>O$#T$` z88;F$j;^{kv&-Pg*AH1dl*q~>ls2h0g5MLjx5w~tKlT3Y_-U`S_8+}s%C@QF`*g{Y zGbfZ-6~CK0zaq3{Na>(*=LGK z1!&7qQo3LEnlnzfDFwGK54|$_$E=JwyVw2rt-JSc`@J$^LvU5m(t6zgfR-Q4AzUHi zKc!}>;!EU>UL)N57xkgZc-6sESNmS+a-)t{VDrW+fn7WP?t5sa*+Ug!Ekj9ZF_~df zGJSskjVE*0U%n?}df}CYLq_!LKEx-l>pX0EWy0OFMHY4EFIK4tYZ*$q+2ucb@YJZK zxkFCv-!c2g?Usy1-%OadDrelm!QT4imWj9{u|V#ec=y#KYO54$g?P(RP-3r5P`rrx zZAi|xoN4{WU5Bl{cg%@1tJeL{%S(*)9*>B8|34t6z%-F6#QUej999DB$eW*cbw$zG z?|!jlTwQ;r+tTj~ck~A_%HtBo52mkGvqGp6)Fn-vteWVU-LLPY>v<=)U9w~x{^^MO z>{yLa2(c4pdkZ7Zo4byJO&@-%snH*uy`08W75l}@qyP8z){-yVgi!-uU7J#F@ zyA5A;qR$VH`f%QmuTA0gYE%SM5z6bTlM-+3{N~n{nXV%rXN>Q8_Jlic=HQbh+#G14 ztO%wel>HRSgdcvMb?DTRErZ%+Tv)Vr$ae?U%uVtUxlv)P2&4p|JU5M}MlQ=caenjR z72ln+Wc1oGamv)IM^;txC>U#+Y1D4~k++QL-*;&5uFEzreb3_qjXl?8c|A z1IcGb!TYKRB~?4DFMRBLQ_GH8I(Jm={u7gWXJuSo;p+SC;kjpXeIqEJE_LxWe$LiiRg?yS455zDeFhEf4KUya2kkAJ+j`up9x zzCBbgW4?REk*?=6$Z6(RLid{b4NkaOt#^;tc>-Su$BcSl$B z9x|uT!erl|IHm?gwF*E8i|LqN)o^Yi(h_+Jpxo1&%M^ z?eVyOA@4|0-G#vUi+j&PEOHn_am`#(00qoKDA2xI+7|QPSUbsC%;#3!;HOd%K@b!t zPDaQR+ezqt#342lzSt(m_pw!x{gzr z_zH{DYOKfU0^HTbk^`v1VqD@yOVe0r_pCXtk*_c1_Zz4iHI<-{GnazwB6(;jZ`7_x zUHz4ge1}%Y@{qC0&tY>qIwI`Nu(F-+WR@879*+qIU$8jmteRQJVlmdq z%sieLR-~@7yp5M;iOOY5(DHLCFU41RD$k_7Ec?LOGPKLVt3bm2E4b|illXL!71g`+ zOrq5QQOCka&X{xg2(Z&1GNcxHoa^b+hEGp-d3uztT`XJ4m=(NAqKQA7C3`!8o<2d7 zhgb0XZ^E4OCV*=K7^z`+lr|=Le9MFWz zHb3#Yrl5RBeOhXC2ceizEWiB;3r=g~{GWJQg~}*G2CU^V$!Ldg<`W8xyb5JPwpz<8 zCt&;&Vjt^$3aL93lI*&c&rTR>^Cc=4_!I_#xZADcL+os|`$Rt9A=ona;+?#c&Q8dh z`*|EYDO>Hw`p-%E@qTPcI3@iL@RWdGan(pFf7cOcoR-ZGVDaUQ9D0ENT$L7QaKmqz zYbc@DDN+5QYjkAKgZw$n8HW$@d)P5|^dTOl1rDcim8zBunf&AkuP$H5-Sa7 zw3;JmAuXQXj4=eQ)^8Dr9xF#2;ZH|wqje$elO&E?j%mLFEju5Q+EGk)XJpNz*qyOc zzIPOhO=o4lqkI6CTVsy#m)Otpvtwx9IXU4NG~QYF=3}`0g#G3|e+s*Eu!|t^4DSV* z|Nac`gRitgp4j>_Gz5_2Ve6b^hyJlTY;->X2T=$tCtD4ydShRKB{La;a+PE=lkxGHYqOfe&$uc_7GmZ8s$5ct4P)2j?n0gveU*yi60l_SsRtHJ1gvou6V+AO;w&~w z0SFf+da?lsQ|P_3Sj)Y}uH(E+~|f29Wk$Wm+U-`NbUiuRTFV*sTWW; zkP35wzKx#pp7Xd~u^Yi*vktEL;U*m2YuX*Wg0({6Mo%ik@J<_!z`v^4UlTBcGx0TQ zKJ`Hcq7hx>Oos z-he|O(U%5Q^kp&z%+u4c(vB-W%`B~k99zu)Fo}R!VavF6YfIlVw{GoBG>O3Fk+zJ9 zg{$Tb+A;TAxJ8OG2PH0_G-TA4qHT+R@g!nfpDkne-Wel)x%BIRjb6#Qj!@Z`AP@B;{4Wc)?+^eq|nJD<(E$_>9`40d&=T;l)Y z$Q*M8+b^=Y9Ceka62XurJyUHvN{)feVy0k=s#dlQoG!#7Fe5qE3x-SC09LkH+?i*> zMJLC3;c)F7;L5fXy8!ge7YU&wIo=DH4}NRqT93hEB1}zA@WNsE0Im#AfRFaoV)qoJ zDICp^W3KTxLsWB$fIxS|P-5tH9%i;W&q|4kpWIo5mWbP0l4B!~IFly@3Z#4^3KU4Z z34(nMz*4sJz&9*N>y88yBo82fDMxyNNxG37Xp+9_I-mNqB0U>a1}f6gQ8_5=U%p%N z6@;f9*$Se3kBkG6fvO#H#SI?*yvY=m=%Ks-J>-8I<$0hy&`Wu~0x3s$kx6)TvSAWl z_YYoVvNs208D7Gnuh8f+V*=f(AUuTUD2Vce=YmGV+X2}Mq45?TQ?4D^kPyg@Be{}lhx_nNY-aO}4v<;N+YnL+e&ridq#!&EAvNN6nA<(LggO^#L#nYT;(f~Bec&IOgx z-gZDo-PRx3pfOqv2-$^eVQ;EZxUv|Do*@8*C2kwW<3Llimu_gU+Xq0Af-tE@c4^kT zuW;=Nopo`yv}^)C=-UJ5FA~t0LTFYo3js}cE|>UgDOs1*bOu+-oQPFP%x2fsHf%M6 zVM~t(A1*LA)a09o35&t;GpnJWH$XBbTs$z}(+qZv!NySaqvC70a+r1(VGJab83L+2 zMMXWdYyfFs3|pWSo^-(An{1Tp-pVzjH#d6AK>=E%y%z@_h8cf)faZ7>V>3f0szA+PoWe>% z0uIAW0}5ibs=zCJaN3CXict>k@KZ&S>FPXy(N)>hF`$ZiRsDZ}+V!t&9Dq@4ZA1}d zQ63J~s&>52lD)V|ERt+IJ%eK@Uh!5jqco4WY5~C!GfWP8`AhbcqSY(Go&?1-RM=Z~ z3ehT4H=8L;Q7A`+XbA$eLJC5(__oLpJ%4d)Of8d}I0$H5=+Y1<{|SoMNBj8 z?Z!v}ri9zIFHHisX zWjY9QL-VkHTP@itwG97GMrwPVsxA3o_ib&#WLmB%Kn{!FT6V6KELsbTRA?|wmTic; zX0*0~OFd4j6+(`WlXi3DVP1pmw}{hPK7gr^JHbhKm%8aH!LcMCNi$t4Q$OLGl$`R- za1}9TnrsOiSLMn$ZLHr=(q7~)$Sw)mGw$W_+VcXZ%3_kV7wvGxNDp*(f0?8mX6$G8 zOI0+hhS>QV)wJ=rs8_G9J<2w_+f>)yOT=?wOD&t>+5BP68IEnTU%sfF(BK)r@v7D| z5a}a3YS(Re%8#|?I-cA9rFF9h(b&WfgJ8I(8k^m(chTBLRG||SPSA+F0QH`YJ+yca zL^=fqm@#CS)M9`mR%%a0z^&;tO`C$D8$Dfn49oFvOxGsEU#~w?Ya?Hnq1C~??Y(Dc zKbT4HvQcuxOzqKt(U?t953bW6BhSs$o?v6;y}8;8C?7IQOO~g%=!RUEtF=ODBusFO z!hEG%=qs2?ld+Wz2F4f@2e@jCmfL1&!)Sh-tvwPqL8DV}(9c{2#f^!Wi%oqpNp700 z)dsOwXKU%tOx4uJX)*-tq>{i5rM#e|%r82$XL{J^DdR_)(&1gxjE;w9CYbZ5M+Ss3 zO%9x+#br&?k}%~EAk7*ytHa)*>Cy9Tr@{~+gZkNtfds6cOuAy19C5E)!GS|I&5hF$ zLm(0erB0?7z6dYPYl=9u#H1W^C1ywExGTyG4?TW_gXTh2fo7s2;{}2$2qVHAln7(T zMlkd%56H4oR>>cTI5JILPt8Z)n3y!Ghqxps&(-2POw*D*vTvmfE2c>1nIdVvFwF=L zLxgGwfssuHjSCy26n%3Ld`o!((IbeCVv)8d{& zwno`71c^$ML>j%sbwLb4Pf%kif=6v9g9D$U!nTv?(oLS3r`3y^N{0j-2&G~+H6mPIqRe0fcK$P8i>r;A%^okMIEYdr za+-%Dsy+B4SIpPK>`+By3-^!*=4**olt)hub88Vz6%A$>%Sr-*5u_UE3F=TEqxDEN zTW_HUG4TnvmY(9r z_=$yD%^E5boB@%h+|#Hq38h$@;yJbLrX0HvWB!KRv`}kg-OQ2^qmtG|S{0mJskumN zl!Y09sbGZ)rXZ?MkpWN(BLXSWXpJX@oNE;yp=uNixv5A=O@{24DX{GzPu%>V2n|kC zm>+rgpaE-EhYwo)!$%f#Qar>8Qcaxj3#mWV2YKy?YndP9F_LyrITS9jc|XW?w?UrF zGQftFC-b8KACM^XV;sOB?&e26K5%WT5w8jr;Y;^oAkWhV=|FtuUyC&rm153uXgx18 zp@T_efAO+r15(NU;$PN3auuJ-*E6m{?qT==L793$6B%V?Ifz7zZwlJvvE(R-k9%gGR-foZ4w-4UwH9XD z?Tv+*R;~wS(n`}zW9o=?nQn7Gwo=>-bD(5i-YL&Tla7=+s7)cH6`6TeY=wUMa?;XRXY zu9P0B2vhY#Xg!LMv>Kde=tB^HP0rk?Wt!R*gR-O~O?k6q+9nl1cy^PP1X}*J2~FQD zCvMW3g?p7bA)$AulJ4%}P1;x%0+v#c#@ZHaB^5n(vlbhatB%nzx)j2gEq~gqRS#B4 zXaRO)z~+?KH){_7d-E+?Gw}D5E!ukskRRHjRc77fP4khMueD(}-JSBa?|2qsEsCc` zFLlET0ZqVZPLnGIdgx%Bnw`y#@TI_@@)W)Xj~t8*s186Bfp=UQUVWAT z58!gpcC7*8FDtiWM!71_n~(S%Xna3;zxjA&hZbor_;@{hT00sb^LA+Ax^M*Gb*u@A zl;k*sFwn20r72tlc_CYYtcvqBw?YXQwrnns(fvaR-3p( zLg~dyR_aKcRfXX7lau#oj`je62SxxifvV_+3JaMLC76mnj;a`p8A72Z5wCR2aiwce z2o(A5#J%{1?g#pK~5AjM|=5UAdVOy;c1gC7DiNEGuosSo+;KJDRX z3_El%LVgeuPrWo6ugYcnwAd^JtI&UbWGAXvRB0ftEPq|ajxe~ry-mV`-$Y>!vJlNg zDvY|7B$TQL5~6UqW z0+QgedLmI0C`g#{+7PL|+BBsn9j~!WpefQ;Y$nP!#LTYE{Va zI!p3ONa+ZxFM2)qjOKVAg;n&L&H$4*l&o5#t)!W)DX;YExCB^{s?@=GQwq>OwE zLgG-7Yd`$fv4ZX`>lCU0_Q!?jCTN^OEt>dD0a>aFXP2+4Un#L5f_XLtkC^dk(Qvb!R~IqY3=AZ@Xm|c4GL@gu00b`Z$S_b&C3r2otU(k2R!wts&5c_y}fhoFXTud8%w5 zE)o(D8X;l9dS5cRHfq2Y;KSI|$dku_BDR7^ zPnL~LGIE6!c?HPAY~n1a&)BV88aEZOYs(q19y!;ePQPk33Xn8tP&uS!cC#h z4pI67y@4S&M?M!IR$-HJe4wa;0hb;qk`ql)ov(x#b47^KE0jpG+D~Q&iYH#2OQLfM zd?N#60VGz*D3XHcm8YYV2)Zk$7+Wy6FvzD_fC~0D3n=6!231T+X4lEpg9NKT18sr4 z`H_GtNlxY2Atd14Lp%cRZwfe+0`_x2aGwhnFW_fO<^+q{PzCZxu!yt|HVuPI@>Z~T zqcXLDITr-c7#~MV4XHG}!^=VwN%Xsf2&am6s!2^HZ3z(wV#;4b#AulwC0gTsV3cS9 zb7pgthy=%uM~UW0bVLhhWG*6w)Mw`S*U5S%w4XBb zt}nO89cjjkR)-u|RaoWV%A!8#SyfpKVGLrDgl5i>t|akBCDk=F?h#f=CcU>=;y3HR zgJbezvZx6axhq*DMr~HBu^HLCsn%P~MYJKu$dLh6L>f)pHV4?lI@Y&Xpnhid8A_m~mwVJpGkHyu*N9dxu z)$w!Lo89fIi{%WTp*6%WcwDL>?!}`)O|cm>KdU90;c;&*P`+8dT}!M3(t5Sg#XaN) zwZ#g2)vqId!&gdOk!pHFc`EMcQ6*qG9GN%kilq*7bYeOPM}w4;RZ3xm0m@kqNXwBSd%EKNiwni!NZ;K4wO-!t2EmlxAS5{}x_&@%Dk)~j22-mt2vBr&>R zh?w~pg}QIfxdOWmx4o(0FL?m4lwPeb9t1rT>Wic-rMyXZk+#BzFk`&ts8@91SNbT* zW!B8;;wj9Ih{;i3(jS*j@IeQgAo9TmBGhCr={MA` z($NAd+~AH41pV-+tAVH=qi8`mAB{ni%+jVyda!}0179?tp~wL6KN>=sddPPhiYM_{ z+z?%QLtbwv9;Vrwl#@b~gL%eVnPR4gUnXZUKsz-O2@rz*jYQ>|DB*=g?W8wxW4M9+}TLH9$+d01}kT%%xElXhnT@&<(tB0o-My>EEQeePx+#WClRoec9`_G_Xv*Q6$*6{*9sC>5;0 zPr<68+4_pRSyM3#zjmR?t@mI^T#-S|)Fe>9nYb^upR!5JK2~l7>Fs>1#9WiTnu$-L z`Tl4o-oQBO&|LJzw(`Q}qIuwK4S{L|x-iglWrKS~(@LljtnnD8MA%jN#l4uwVAOF6 zmz6R?KQ-9{uDBK%^_0$ds067A7emzJ(*|QKkaFi+P!DZMaC70|tM@1rFE zLmzFh!*21kRfA(9UrUG1y(+tBT^Jl zw&fH$zbe}~Me=pXq?d93IFK+?jL$toIFT#gHtjZN%8@5ldp{al5_U4aJH!y!^PRnoMnT7Q|&H)AeCy z3z6%4qj5FiaZw|JxCyBmSpr1Spd*iq$Vw{9ySo@hDT??#A*!O6>OP@NnU+t8`ZO>> z8ktDGibxFm$$?K`nz|~tKOvGMO=^;`fZ(CPj!|?~2DBDyFyC%%EgqryHnxpYCl9m{ z4Qs&pSHS>GAYKy8=oQHIA^`|!9nnTKC81DC(wC>4Xyo^mXWEE(Ah)*_NpfpD5hovN zD^f7(GTUNoU6uXXB71E;itqeT*)zH1uBQ+*xl?| zbQxPd8O9*PFA2W#oR}1_o&~9^BhfU8AJmJIDbI^~I#RVjx#c+#DL;5#B*L5-_&ixs z?sd$Q;2t zJNXm{*wMouUEfvS`;r(^LwOzmARi6RtqFuCAU0q+9xxebMZT-N@{)*;L17a;&0o0+ zNY&m|)_GYx4LZBNES^fh&?R?EK|1r)Rt9`vS0*UhEHAt)Ud6?WPrf2vX5-ztuZV08 zF|Xf2)b+=nq}Mu%Cif2`lLGoI(@<}m9++ft+a@&^zS=s3XY$M~X}B(R6QY2FF;mlm zqA}RLy(8wbrY?<~H{9s?6ATL48s{R2>_)Ux{~LO}(kRmr)6_y9d{|RUQ6n^j8!q|r zKgC+mb8jaxi0In*p-87q9)TZ;V;nPc(I@bWisj>@!iP4lEB^ z<|nhpTdQfom5yV;Kcb*UclpoHMAAdbhw|A-*~$Q;G{Qr13=oVNl$1zrN+y{^^h$v+ z8$5Od+99Pk9h|AT=&Stfn~n{KdtL{K#ZuACEg_Igw4KfD^YHV~>!EXgdpt=U&}}A%iLH&2HkWy8X#E_ZC5y__|B@ z_S%tj!mLq(9@1Sz!=_5@E^0-XvsW^<$FvF}`9QZK==N@R@qQSss*oeFP6;i-tn?N$Mdx^7Fh=$H;*MjV@MBjt)HzYaNz{5yQ1S66YSaN1WwxXRO?oB`B0wq`NNRE9J-pb#7VB0j+#c2j;4uh-r#k~LVCR35WiSJbzMD4%;IFCU9m)5Q1tz_`ujE zlTL{u+&@fIJHy}4bRM9EV&kx^@~c>s<++QUsf*jqT2GkQv-46(C(R_SRMIIk$-MF1 zEcmOLfwcxawWK{)G>lyQ#s^jVSpBz&O7c9PY8m`B2+3PeKQYaUkhFx)1?mR7= zq325ARcp`7>Sshf6j`8Oy4c` zsMvESy~4e_G*KqKMP`zR*$S$dl0411T+N_ZN$psDmb-Okp(#HE!AdT#g!Kjjqj{iho2uoD9VyoQKaOD}`ZU3XSk&83^sQ zxgesm)Nl;U48VQ)p#PW}y5V@+Ap#OWi`k6?gtQe@IGk8^#LUGT=>gh10egVr+{uqA;=0uPfBC!2U3L;SCSqi=e}vcm=}ysEEQ|D6d}-vG;=cuxvbZdpZPg0V5dG zsK3+9{`M#pqRmhmS%X$+`(uGZ#fQ(N7Q5kyzy2|htQeRqkI%Vf8wOW3m}jDE^37oDzvqI ziE)=i{j}XG(FZB$L^sxrO<`5229!nhB}(D)d>Vj00_2iQ;@)cI5s5Vf!1h-^^#L2s>|KxcFA*2e?nzVpP}G75I>BRBhRMs* z=_R1usW}RCx5!fE!6#HuUaI$~E6P>KVZ@iq%_6Fm zY^xEZYEZ)msBhyoIO|C(X-P?%!lKHSq;(@!t28u(%9_ma5QwxS55f{a6dnXM;u-jd zgf#kEqvf)zA~=|g1R%hcI}p7`?z<{tv$~qUs$!~QGE>Yx^Vuq8G@Vx;2gCsb>5)Js znpBKT0hGmWrQkORpjD~op=0qN;8H5AEU^6enn;dTYMg&!S{<;Qpp%Kj9di0L*zMco z)@z~|xAL#LE*^#+54fT9aZNmQ7$Yq$z9w2_#~UaxNDjIo9tr|`s-SA%f*~xors1lT zv+~Lf(IgR!z`6#J2+J%Svpyct*aCt_JaqCCe~3rzo}ZgxvddY7SkB0~e}K>f#KHbd zDFEC&VZNZ%^4uRH0dc5+uChMUBVDhJ43Zx{X$_JsZX%RhD4)M6{t@o6gY4#TR#V$q zx%j3?OW9#g!752j;GQw(nb@%ogav+S+`{6@H!|%O);nDC#arSd`$U`CxH3`hyd{!@ zaBxo@B?mOFD$m&uPwS{$v|l`qKmg27HMe~zj~o#AjfA6e_czvdamesYdUWc~f!|`n zsHGod8m7y`2gEA~4m@xW0Z4ql2zK#Ny8P;(Xpa~I)Q-$PC=%u6gK8P3{vlEME^Ztc ztIJOgiLb0?#qwW=M7nHxSYhaV7{PyaxIanmJS@VD@sNH~79bFqN9C2n;*ebRx*m%Q zr4PNXKY-uNNq9rA8#YnLwifzb9IaIl`V{S-Bwu+$Ps2|P40=PSA6Z!RhW;H}?0)%8 zy*GpVdEza-atawIxRQpP2QmdzprdxO)mhK@0q>@wnIdbxt=Ed5qB5hCvEfWX$0t!) zC@KxEQs=kz#Cl`(mJ~pTYjtcWmM4XQ1UiNYFX8bZwef-SPI~j?vbXhQEDaxdTTfwA zrR^R4Vfn#5dK6ZZdflV9k%c*~kFz5uQ{vZ6L zP-2E2OBdXSwhYpI7u-Lbff|pxJ0p+bCwlrnsK1ZjBD(sZj(Cio?B6m7tNmCN*F87d z;|-!z_aVIzZnS^nAw8JG$o{C6o~kd@18}qY*j9QRTjE~aN*~MEQu*Q|`V)Sm)P45M zSSE8H(VvW5u6X+rb;8p|9&!GjOk=5xepGh>*R)6VXm;Ga=287+x-7rS<9cz}3RNOJ z$)Cy?NvfjiPe3MdyXq78g@F|^rZtvuf!IJOCQrWJT5lM(7&Z*8s#B;4OEWO@9+7zy z5V@Kmizisa*kZZ2nf_GhOvoH*AN&#YLr3-G@{g=Z*h&6sa~*etKc}a&xw7+f`cypP zpV$A5A1)g9y#7z_PJ9)N6B8M;%K8m?n9L2)2g%8;^+#~ec~NV0_9}PSKM)FJ%cQ8K zx4>QKez|(Q`{_3N7YwVGdR|~vSkUN)C7gO}e_Op{HMbrR5DZ$3I#4@Uo5IhnRJOn~ zV`{C2bxdN&TPELcr$5M1W>!0WxSTyq3yXr!i^1&BI^xH=O8LC_(FhEK*>d1h`YZCW zr}PNW_S#c=9sDK(l0Jr!%b(V>FlxF!tuG~v&S&(-xFqWHXY_n;jQzD|^@ZSBY8?Dn#)944R7{DKQ zvd+duZXi`T1HJvoVOUSW(z$qL&Le2>diP9!y)l>H2kFVu8l-2U=FUNSWBE%U64v<= zBIF~%`ZK6#OfW?IqKpZ_s2?jI3elgDEeyRXf}3v|dQ)3?56*NlTl2WGTd@paj2#-F z-=N0&F?|g5Qjk5+Ci9;Y5ppHdDLQ(D=}+O&nCnkbwjL`g2tU->~%UVM3Bu7T!=VZ3Z1yTAJ$@w}@=W61+0z1_l!GTb* zJRK5|uO#A`X#H74A*My^UC|fyVxTyV%V%QrYQXVjjGjP48TX2D-%$P`Mz4hlU`LGJ z1bq|`tJlY4d|hjpY#WPT+}b9yV)c(O#xKO`o$%WV9pdzOj(H<14tnOO92Q4oT5gQf z_W|_#c>OIr0u%JksP*dvJyG9|akoQ`$18qYBQHV6uDs*2Wo7*gezl>#Lw_!8w;Ja` z7=q@T2AgA)L;pBtuNuE|5nM>+)9^DzH0Jjpvc5~ECh4PNk5f$2`3vI8v`C|qjU94+Rs9e)Ukpt_pYNB8QuJ1_s4WBw zYWrXcLqD#fvBRCKQQblrTMe>*Kt4i`gYvU#dX<##71BLW^jH#ydOt+PXt~o^1Z|Eu zG!=9&qY{w|Y4W745sPR+kYF+MES4-){~cH_r|Om2Id@bIeJ!iL2P2urHv}K{qK?=c zrYr0f=VaiK!HYjgm(E)HP2{KzXgPM^3Aww?a4*sN`sUnVqqza=qS&aVsb4$68|H?a_0`P--u+yGy$8s8MPU`lPa#<6-7jU#{3Sm4g-)ai+J|l-Th4NY?H#F7TzyyoE z2i;L9o8O~1w#O=42gDt^2TFUfv^UdxhT#WkFhwYx3OhH6wqwb!n`4swNzQ1lXArA8 zU`MI6-K*oiBKOdHFvag~|Mm9W@lh7r z-+7+R%%o=_jTAyQ1V|u|&{67!F46?AfDKgc^-=`v?GlP0D7_szp@W1XZINC=M z15y=GB+`-hd*<2Qpyb~7ci-RV^X8AtKGWx%nKNfjnF+2Z=3zW5>jAMB=y5&ta0gYY zuNQIq`r>)?cV>Oj3GW3ytPj%Gv@^DdQ}ktLEUO#}>LQweD!1z*?$N@UxUOnBb$df} zq?}$N!}!gmdW*`YaohFGyBJOU9pTjWJJ=c%A;Q!A3V2*}2Y|gp{oVs*zU^B79taV2 z3YPKaJu!A>VpIgw8Ta+($2_hURoWj2*E{FrDTAUv5KYWS0Kf<03xuxAA7Famxgqh9 znCp7I8#WT7A36Gq7_+~mElFl7hnu>Kvc>qBAIzoq$i+@t;FcIni8DIelQ-MDX739FjS&iS9d1aXB%#&c_ zFfoN1ekxuBH09!eHCHsWY`iUn@Mc<2{&Xjxu&fI z#QUtFpF*hv(U)HbiSXEO(NA14iJU%oZw!sHq*~Yg4V4-!TEa!Q=U~yUHn?K_)*;jb z_=Teq-*teqf`bnipkbc)aOeyXZ)ZyeYt}8K2ZKclcdP7|qN=-F?P0^JyVaqltr?UH zZ0bD4_5PP4$1rEOXA#0*lFWD-JXE~K0K7C*Oi2SrWH_gO1uomqKFtg)u7PE@>|K5A zvw>dCGvSFJCaQB?k1|DRey>f>&w1{e5$c+U_7}|iP3tfI!41d(fJ(>Vq8MMQ#y9}E z{)sZDh_A5c;^D|NIzB<9f)q&-O%t*)->f`~!NWX7W0%lZ!$qodDRSY=ossYYBh$_LWj%oP#-pBD)(Ap8A zrJt2#UrC`OMPIBEepu67C26V6jG<#AMMKmPH%k1?8#iK<=vQ^Mx0?T#hrB8gjTZJO z_iJAEc*vCjIQMAI(8kfAaI5LUXwe){t~5rxUpZU9V<5uG!2TjaoEbE{AV1WPJFREn<>OH|nfgsvo zK~NbEy$Jm5+uaQq_8qc_v&AYNVF~KfRz#F8p$YWURqXOsv6VUy_`^-KheRv?-CPzh z-A#^(;_tY{bjU=(PlBzRh`oF-m7gTaW$csul%5{(SrHWG{;40x^F-q9P0vre`zK0i zC<64OXzV1BT=9F!0$dGE{KW01o}c=O1mr_3Upva!+Dlg^VJXa|)X5^P{$73o&Yd9n z;!Eg)rT1CnifodmY4Co@@_Wxu4N%mziY8CS0e1ndo-C50a6Hpf4fBiVRgyL1@O<86 zY>?TcrifB?Mlw_|_vdh!iaQPv>Pg8Hm?upRPhf97yaoV6p1IkAN=@+6p*XD=;0d0? zHC@AxMf`*BP1s5Er;4f1=Shc+Vd3ixc-F^`fcZ@97>76>fbn$(J{`|c!uDcxs{u)n zkMmgGR@{RM#m&fRA~H^wWNO z>p1037n`udj-DY}A;_NrZg4C`W{D;dWAu%*HmA^o#4ZJljiEkSkR6PrNm(FSV`x(r zj_zZ~Zzi_sJl8*GiqaO7|&uVy%C~6yi9ZGh4~^QY>aXM zo%TzZmnBKHOOEbW`Xx&0l*423d*lU~s$1enXyWh2HA*LF2Tq^4FZZ>hL=mA0#sPFbb zD@TFY_ed=hO(6+wy$nK(>vVsaSU@GRG4v7CAX}8+a-Fgv^%+h(v%!~Mr|`w1F@jEu z#b>b)m|#-)cvvj=+2nveoBX<1^e|_^_O616r=d%5Lb^__CE(Ytletv9R1)qz{-8b{ z)d6tKYXpQUQ9xPr;9JqBIIFMFPpx6l!uE62cexmr33)j{%x6J97b3@1Oe4tP{MfGr zuaWaRuz|Ii;uWdxYJ?Jn>MpOg3)yue5ETE6D%|`P+=&2vANwtt$i^N%u-~VaE3nE7 z=$|V9Li8ww)n#Zh#Dp~b=>-$M5?tb8s*a#Mram7igK!lzDlE(%X#ZWO*jPX1 zgM;!l%3LX4gOS0Rm11R-UcewgaBZ+As;@Os7p@Z7=*HhxLu50W_N>M+e+=DTEj~AH z(|aya6Fptz68}V&h&9-EZ`12*aDK?6d24VyDxmFa^e8T_!NHi@$D(BG2@KhrR_!~H z&dqCWtm!OfHE(kBdGy(L5GWK-`vEAMM~A<|1k7^4S0uj--5;|}&44=A zTcp_9cz<=!zqD|lbs4;oA!Y>T4k(D80~S*@LU{BotXt8dZPrI%!`u$(W&zpvi9|mh zCCb=n(-s_z^60~TIC&M&(j6j#_U;qq3NvJG6{#BSoE?%xo~kuWU(5Oo@Pnt2qQ>8g zuCY13reCI^jY@nx`f!kHbh3b2Z3218qxUz7D)Qk_SZ5ui>`kC=$LQ!LQM$AiJ!29> zu&kGP9GGdGb4xraa4xwSN6&>+eX~enp8Dm@kO57m0h@99n@ri8MYJ)6c5D`-)p(Yy zffBy9Ma0JPTE!QpwZ6lQ*V#bpLSK{4Z$}jtK+v~@og$nX>;OvgsMih;IO^c*+740G z$`EG`R#a~%1V{z+?M^+UqdP@)xz8F><&EHyk5Tg3(wz>geGE7atl$Pv4i2~ZON7sC94{9C;jvv56&53;aF)TWAOq!aS`g;7`u*tDp zfd2*Ar@+k-4A~Q>V6Ab5P5)PWMSA*iiM9&G!Z_ji1WvM9ifx>o?uVq+hmy0!*Z0IoOXT(K8%Or7k&;!c3&mIS{2_ zzHiPE(NTNB$?%J_{c!zrP20yfKeB!LWcoEntgqpo_kYGNv~@sl5r7}*9z1RT9tXv- zboG0&g8CkW-eEk^LD4>Byk;HOxZgOSdj}x^8c$#5iPZ_?6*xraCL{&IoCRNcC*o_h zu)Ues)?Ym&7DZSUn9urXg`<@;j#3Yc7yegQZM&`>7NZRqRep9<^hfaMC@9!`dgd4~ zH;evuOne9#)Az?f``1$VaWM|h6D>S0Ccz%I;R!Jq^3gpIy@C<``2_arc@%w8Yy>B9 z>?ELliu_KAa>XraXtFj0bM|9NCpk}vh5k4%8T!0Lw@yJdkV`qIvF*&Jho?pApR{p& z#Aj_>?K7Yzc<}p-I07w=^DNX+XUG`^J;{l)q7g3iD3y;XlS>ox#dL^bYo5b^meF_T zz_5Hv56+1UeAPRT;Vq|6&x^$vLh_Gdm$8{{{s=YS5=y)PvCRsaegRs5X;g4Qyon)n zxCogeQSc?4J94SPB``J9Xz?ZNS1alKB?#L#Qr*kq4FDqRGSmhqDfWt(23^Q^SHLl@ zBEPHX*-C186`fc?Bd>z9+US~l6;!sY1(z$h#1NCvc?Htp^&qv7V&fMcG=_&2eynp9 z`~(IH^*XOvQr&AHY6ofVHLUW*bnqHD%N(kD9TLt}uKm|Van5@FhFHcs=(t}1&^+4r z3s7@_?*D=wZJ_4AqVL(%_g66!^(5RBAG2`QSM!l9vazpr&A%xE4F6nAKG45lAIg3t zV(IX20LvMwa7(;^a(!=!Z=wE6F90oHPHz=}i^!v61;P=rT<Amwg{!Occ2S7a0l|XsJnpKX{vY^ z#}*xYKo##nyD*a)-4jdDqg(gHRBxdGT5unA=#oeHm#4M>@_hj4?4YOzVl{g5!vpaF z2GHmsP_dlec__{SaBUt5hj-jck2@4{P(Jo)?uMT|pYsShkW+Nzk!Z^^=nvrc4E01% z`lK6RY<6j;nDEo|b@H(SXFhl76Ljbg(591g`wu9d7gP1e_`;*bk1?xGQqE)1r_>)B ze7(KUbNV_0EG_H-*20c&FF!K>5aYj>tiWkw$j=#j#h(tvX+8jD+Nnt1er z#jd8T$sryS{3jGPzBbtd4sm^KQY&mm+9WG%=Gi1GY);x_F6Uk1D?i~dMaVC~VSOuP zGRm9~G6lB=`bs&Sy#!_}StZue$LhD~*`zkvgo`Tv!!vgS{iHTEXl#1jHolgiqc7J4Uk zvJE{}<{yE`H=M2q$)3@p4AaasnPu{BynI~6343#}EQQsWA1rftVayAW=}=o94FUJL zknV@b*Dwb2*QfVCb1{UW8n*df2Y9W~Z0qYlOWtgm3VL0CJ0iL1GifA4T>qh)AK16zt#3+6!9%^-eui7ps zT(a7(R=BK%lT)8?Ss8&=+tq&qhOC>yfynE0C0w%Z?&S#i4xXXj6Cq;~QIUURe%Hon zyzeLurI{T+EmaJD+0R3|zAsTG2IBaJ#8CMCtfi`v@(5}Rh>~3q^p29O-oso8qu--s zgt!Xr$|VXd0kmFrRVpFvtiq`uEoVa6axPjnutBp&m&(fO)GNZS&JJhA9_|-#%J(FVXOl zG6xS{ybzCZkD<@vWg|P25?FKC>$CF)grH&LEI(Y(?c?$0D?xGzeQ z@!}VN{2Kj$pGXJDOOPld@1g6D%gEWVN(R`IX>VB>?RQ?{cxtoHrfX$o`{^}I&JPZlC>S>`d$0x$}=K(K=R0t+=QRmL(po==s- z@p&Ru_67CpSP_ZS=uAa;{{i5kje`Tc3m~|XtO$VDt^`P7PFBKt*9)Kl0>CDLhAcH^BmNbhDo=wwa@OGL8aD{Z4hy0Jzd0sqbR^f2&h-uB|ImX+}NyE_J9U+0u$5 zP(xNdAn+7)maw2LoS%_4lB|2VE~`0Pn_88ro2@j_*)I*$IqcS|j-?3Jz~1E5wy$Rk#*l zgTYRLtZkoSL3RpGdUI$=V;L>xC`e*xX*2YA4xMTy%U7!8E|bEC%M^&b$KVLZzbr`s zq7lfr68d4U$OTGh_2+AV84?cf0acY`_n=COf4hnoJ_xgZo^ zUBq7M{T%4`7@GQ=T!DVKX(1=K_+D8yE|3`KDHbwoRsA8wa%TPWFdrkVpGTBsC~mzq zVpt}^_5*yf0F-j6`tvgVbx(ys-MIgA+;!?N)Do^^$G}j9>wGF!w*+;_5AK${m2eBl zjxppsFRPb6s@pW}#}sxexB0qN%#-mr#kG`4QOKxm+y9#QQcGF2{E5QElhz>6gaey> zg1;7k+E2Ng!BlA}8&*8yh6*Y>>xPQ;Q#Sz!=6h?w@=R(at5+->sr`Im5&ZP@>c_$& z7ie%R`Aq!9!o*93iI=UBDjMEOR(at+=D`ZnnA_{crra5 za@4AgtOQN}zuL%H3TrEi(>HBo2)wuIwgtJ*Z3BL14Bc!42Ine;x5c(Mhf~rJ^lU3% z4!p`npIVi1h4R{h+KnZ@7v!MK9~9(utOmi#K)Qw2G2l|QLgcAPR*mo)n#0BTgzNpl z*tDYKdro0794n#s@&_BOd$X}>#QR|e)_LL!69n=$U;A!fhn_1&x4;$#P>%dqs;J5N zmvu}@&1GGT`iuq9xwjE`sXlHht5koo3st?TDP}m+9Zj*~@QcZkw^i)@!<$G) zriY{@J)Hps+@vkAuu_)edb(Hbe^`dWs(X?A*8}9Zv8z`z?1-D6?QA$!lo5 z>)?wx)`ZSE3X2E4rikCD&ZGt}$tYZO-r*$~@8^y*$braA&sU+0+8XM_IjF(kQ-fRF z$|CH*ZN<${>-4qE&~i`k#(D(!=bN$Mt4Gs^jNV;f&$xMY;P{Cfa&z=^$lyM~oM5B0 z@fAn-$Y8NSKb-5{kp02q^?OsciXJ%Z`nqM8ugvLH(*_}Z#^Obbr{BGk{lg6(y7Z>} zs9{l6<6we^Q-kai-5|AbSD>+eqHu<{T3l)}<1G-(eA@Ju?1gvM(z?o4#qofh>4e0c zfoRw#V^g60U1eFfr?}hY2pp2mVV{N_fJSzek)e3X&g9dnRc;0qbd~dAM>_TIU?yi! z?|*7?dKiMN6`wT7302dEQruMS{DZr$8q~O--`q#^HKg{{M%Q!q;XYV1m zrEL`O)5MXQk!rXN1T-)+ye}-QK=sg?DHBg_FG)2a?K`?(@o zMorMJ-xZ*SZW@3Orl{Kd0qNk`eF)6W|>|9WTm@`DpHYeFBSGM3-EJYdaN z$8UG%PlMIp{n!M`r*IU76+YRpy&rFi_IrRbT<00e)VY%+%w^9NTko)AzNB-#Wn`qc zm5jpn0mRR{V1?$>^e(b$^pk)ABnnp&{nQ1#^Z6EUoEOWoEh~a!n_vT z{mRnVAL#qm%}=51isY&D_F&y=_Bnag-EuFd%<7R_BPg@Zw>QfOnrf+7xk|EFr~;I zS+mSqeD(p@dhPxFXyv;y)xc}V@8anEB@KEH7k1uqwSQj@Qt-z(@tL$4h(7bV%r)-N zvVTGT_NA*%Ux-{vZP!d=sJ#NSi+t4$?l-StLNsQAJBHQux0!NyleKtq02`SfWXwiF z2=4v~?_po($7*u0mDo4CJHy}6HV@$V*P};Z9wF*cI=jsdsUp9Zv5dax2kF2DTGdYu zDekt61FvdX#^H*@*8OE8bGd|lYgt;?A3}~1G;^Me@PlC__A8u@OAV0mku9;wTY^U> zl3EwVy6`^+$})kL`U)_&!!~sRgbywE$VB?&3%Q&=+5_CTg*x-6487|^Zp{`$`QtBWp$ zM7O~re*NH0+-TK_xVhfAvzEyrrqU*Fs#OVI{jnbdG%^y}LOknZ->lQA%1jwk^{Qd@ z*0BGCU*MUUD{%Yl+Dm(SzQr$4{~U#y9#iH_8JWpOb^I2P#YOCJn`PmP*;O|9;jy#r zsI$P6X)%9&q5TPUCU_NaCbq3(y_;3jRvB2Cdw}yW+n2#EtVq-2AQapRNL#kY3A4Z^ zZllfjWfZlZB}@5xtrqE{SwPfg%9lqnYL7vJ#uW_*fEzNXz_%1uHOr*#@#e@6DGE z`t&>b0zE>X3h7Cg`LZg#n2Y$Vc~8aHT!8q7^Ph@uH4pKZ{u)1shAwz2>y6d&1xW1v zOvH4fH&F@1ZAGLU--nd^qEbq(mGvooKD^(4{7bU2Mh-GA{UuVjgNf@dbG4}CNgL7F zwW3nS?nTNkPp4F)n)^V%etSBlD)n51GQSs<^386f+$}0)(Oh)!m9?@&@B`cisL6Sv zFRr<{8D}&DZa3XA*ka@6T3IUK8@4EcTofiUp?8gP0c@wGMZm+U!CfN*#;Qw88L_l* z9U%0usJ8ZegI+u?D&@oi`BLxzT*&$FI?$!05g+*Qzv;n1>a+97y-TAbcs+VBxTuuT zE~E@CDrNZrqzo%6#cwWBMi!NFH`jx97)n0fjb+@8@kOQF-hh;eMWwv-1$NTj^Q0eD zz?CA_Je=~EjFop`9!~#Dq#pRMdrf88fBj|8!a`D5{+v z`_Y3%MWxi)B-;fq@dro1Y=)kfU6vbf8U+(JV;<&_W3x<_*Rr*xQ@Yb|Q18t$-TYcn zmv@YGIrShCz9M6aF%mO*^b~{XS=(L)TMCT+(MUq%FI%9n&7;m!jYtHownA5PjAl$V z(#+xTYMg3RgVtr{D&rqmRp-VVJtur(C}Zr{b0;E0wYeXBhWYMh)BYQs*#_hA z&q4K`Kf#zAz71MC7U=mk#`}%$YEP|gw8dqFqp4!saiG~rH(kc$2rD1*1X>v($$*~q z+zq2V)V*n0#)rXZOxx^Y>$M*r`|at;1Dla|- zmU{osjkf`dUk?~;u4&ITQst?|mi5?T+1?zXD1V{xx-783+4d#Fh1^T~qI-Fif6!nv zz}_8+A_$fOqW-Iv+Hu;sXe3x z_7L*TeJcLw8pO|kIzE)i#ipX*uXfA&u9^qI;JsL21eXYkVjdp`?9TCrw)!|@?1+pC ziu6P-<;ZA`j0}qKMDF6qAdZY+R{*Q{A&v|K3w|z7hF3sZSWt0K+I>z7;R3~j;2U5S z7;@N(q=Z88(3W<~DjNZnDb#+k!6eJ_*;Hc&eI-2Wt}53y7qVo9uiDQMs4giw!`1)1E&FSXl(lGV@Wno zxCYV6^s_5NZNr`Xj- zo4xxuPkJkcc{fNV5+F{cw=Y1#^*t>;3O(hRA7w9d5-epd;r8>=7i7Bpfe(iJY2q>H z=5c4@G0fcwRP4Bn&y?sE%nJM*+H=&`0U-~VO^1RZh;$CaTM7ZJ=^tZD^oKK|!_S%N z5M~1;`mvtM-yxV84B+x19QZmyp+ARVJ|1Fp26cDfHeFD3M}P^d0=~*UA;i8_FfjNE zeR$+1(B9)RG!rfd?E9X8_t*5V1Q;pCA%Z2RAJ;HTa1VVT0WHmxmJiT;4?UeFBR4(s6QD2(3OOMQuDDuOmtEY)fou$ z2js0#c;#P2lak4qgaD>`_2ypl#WerjS(HGpk*8_KXqGg=^ zSkMLw86?5q8?rffl)oFIELP2Y4|iSH27D7TVYsg|EaPkLgIWj61kQlMez>HsDLyqm zaFHl%uh52qmdQ~fL2-8!L?#0t7%`xH5580pEg=RyLJT~WLVy-@Q8(x79EYj{ z5(2qRhJFp_R7Bua2TugMo-8wJVweC?NDY`iVHbpef?)__D7GzyodV4~30(_($)QHF z#tZQ-%qegoBdROrjb)K|al}GUhaOuv@l63>YuY*kl^WCRAZ8|ndOF~o0|eN;U)lI7 z?k!uw-7!p^aAPr37n1&DZJ*ZJHv>@%W{lTOg;{|tAWJbk-W}y{q8k~j+yV%#?#V2lb@o>#f$<5t+@~k?0IGdymW9QZXy1F`_6jU z0HYlf7y-M;`X=C9`8EQ9Lqb?=4f8Gh#yZfyJ10Z{AG|D!;kxI80r-H~7A`~pihXKi zY8nFV1=`V*Sg$_#lP2OeXANY`a`*T_z=Aw;4lk8(Yy(~e0Spwq4D|L*ks(nRPw8d-{ zfpsh)2rgpuVU-U?%8#t%P}ntDmKOXhyBRqy{Kkug7wOz66-mzP@=XZp=3WOgpo22h z;fA*7)XA^>0-J@4usw!?9v5i-Dj&iAXwXgB5$2a?Z=&dWdcHt5rqBWyFJ%1&!S<68 ziMI+PhTTFHg^6{n-|Z31ERdf;qgL{F`H>aG(z4&>eze!`wj70^*c}LOFH(m)()B+U z4jNi6XL(PuGp2UEOn19p*0EeKK@7C_CHrD)_sc{0!A{Ityv9UQoEbYE4OF}+y`L3)Gu#H7>hae?fM{)OLr5axG zBBt7ZAz|!yPewlbCkZ2$_Xrsi!O}3&ixM(&zQuF^<&*y;SLAqz7TLwwZb@j}Q-6>j zrH#VXLaPkRg}mo|9Pza9E}CZEhk>FNE7o{IqWJi}{FJlboQ1>OG#dE;b}n9t;cpM* z{)(#%X63c@ic2yBuYazQLE5<&V#n_aoqNyHjfdDfR#Ev!vL_mz_y~f^)pX^NYy|;i z%|D=&-Qo&-EWb4nYdO1HJ#{HVEjQqOx7JkiVH5p^O?`q%d&;I>gXLmvUzG|g;kSKN z3a0QFU)3CTb*Fq)D`P8F5J=lk9XOapgE+WB%LQ_NL#Kq|=^GTB#1^CPinIN}jSFZ6qTb2TQMwWQRb-cd+ygRA&qbd0q`x zF?@T(C&8*D6ao~Cme;y=1gjIg%4deE_%cIb_Bfc&ktTCB>tU+SJRy7lP4`27cpX~0 zE`%z@dYx-_RVIXQV*v?uj>4Ny{Unttrap-r0&<^hUNFEcBg{7(;Q9wkT2f3+HU~<2 zuDB{~4w2NWxT+pE2zi}rtXq$fd6}Pm0LNqj%U{yw;%XB5)+tP_M-UaRK8-HsB6qtpr{zF9(L0$oTfMP{^mg>!U{2G~wh{TS5@ekDU@0OP|pNx2RFb|B)9~9 zo2VT0S|YOSpm!40GYA%NkVEGa)!z}cDWlTpPcQvvVm|8TB?I6Urh>4z(zYEL&-MSv3pxp3ZWrG^TIYa_W`fZRiOw;)l!S zf!c`p|J3`pCm`JZs+-Atb{XkJQ=V(Ly0K}HdFT$RS&^89BiShDd_SR zYExeAzLfXisAiUvkoqynZVNmfKdC-JtE z4qmCKJ_U_AT2VcZAgPiXfM(}c0&H^WTqV^7Uk%e#HwciHq^XyUovwg%HP#4w%rmh- z-;)5HDv%7#g?L>sS6K(DrgTa>|?=|XD4J-UAWm>^B1m;~|T3=1!-5Osyfza<)Eu{-8 zK?iE9NIzU_$`wY@4Sbbye`%SFRlUAxnLCW?k5b#}sPMio^{$Qz5sq+&+3s);hj)DG ziaV4w)Ju4w;I$g))lvE!L2)#}R;yf{)pT*)bb|X!%WR%*8g-tlVb%Q@VXeYi@~v95 z=*B9iFDun*THLv%?|XzU47(T}DmX~(YN`hzC~X5H&yEJZ_Fw6hT0kZ4JFBJcgt?R0 z0-jAgkbaZXWBjXmtH^#v-3#J;?hN_#?XxPb+7<%?tHlF5$3tYXig%1!hGg|l-^2^! z7*0JyMr{D}wl5{r#^4avLl}royE7c6uC*0=*DpdonqEgK+Fx5m8U5)pBI@MOF{$iyw<8FjGUexm+$fSofmgM*{A!3s_y2)x2W!i~5#xMYi!h1oj@^4Xr|IQY}-s#^4%j~?>DfSN|O6<3WFu);%2IRTtBQ)$Rr_q!O|`r zm=M9&^Z*i&Ht6TVS54RW+rM&ZLMA7I;mjO_{BBr6*bugyNbG<)lr+V&lT~O+L;*A zj}PUb9uR%m@#_0egH;nY38?%PIEvjg*a}WsLHgG^au5Pv+|C+AZHK7{`t57w;7=&m z`7?DGfU=uf4O7o>tiKhTg;@Udvp!F_Kb7?vKHN$L$heAD_(T=Ghg((nTCrQ*nQYeQ zLn~AK2uuMONRCj8-M5TU{74lTYTYyD<}x1$sx?wIW%i~2NcEvRjG?em>U&T{oI!8^ zaJ@TP^)}40iYo6G5w3e<)C~hUU027cHznldEvH~x%X4K;Q839IOCi%#8D-t_q3ATb z9ltP5Im|JN&cV0cHFTQ#hru@1(_tquhStqc-60Jvm!&$PssUN*RRsB2;35uF$(h(h z4^vw!7&H@;_6QxAhhtOjOk_AlA+xY=2tucpC7dgXk@4*VzQt7Js_E>NrldVT@+(gON?f%;pBRuN#1YFkY|>asvZ zD{D_VHesPkj?n3BucPN%ve_WfAJ%(S*lhDC zCR;TC$MbTw`W#=!vejTX`Mb=+h54!M2NdN!< delta 63752 zcmd?ScVLyp(m#H7pMB0bsXQUQkeq}TdMJVy6>=hA0aVa??FGwKf{MLeHKC(`1P`$E zj&umkLnm~Q7J7#uRca8Wm+xoxc}_aQ`~LI$U0?1s&v|xdXJ=<;XJ%*1vwUXajG2kq zk(wt;d(rce_8;cwIjdFlgoq*KI2Sf<{qy6RXNsujIVj3!*c>*_bepc(Y&OO<&F;_` zXLzB1Ow;fmV>aEUX%3CsD1+e_lIR}_X*#E0y3KCW?2PgV0_n`oZ74x+I@eLN&hSqI zl%}CP5Yww5l(OAwNBE02ZnHC$N;#Cy1Q$XRnne$)1!AJleBiGR%BlKd|4^w)1UArt z8ky%0y-JixvJWy`SO0>7f;@HY5mksl?u-bbsu_#4MKQ)B>8Gtc=-`Y4n%O)b+ADc7 z?Rp?%f-)7Eo@Mqpym1@-@LaNodQRArJYkM#;*zJ9;{w~{NpM#6#5?1HKKZEK`yaP^ zpz)iIgj%Z&XLYz{189u*d>9^Q#klzBo5q`fr&pU582l(~%o8vdZZ=Bz6&dGkiI&V9VJ2yCc`Azfd=C|3o z!+FIy+HbXUYjx*t=TJYd-#TYsXJ@}N&O^>0{r+_J^c&!u?aX%0a87qlc207x^Y_2F zd3F>3ul$oo>4_{bI>5!z+mfby{A)nq)B|Bm9&wn3b0;OOZ@So zTH?tGkBnAyInDfH^m_8c<6Em--739_Pzmd0Gred&RP@4&zAzK4IK~$vHrGEc0;>eL zGT9hZ)Ckz*F<1KLAGDf zY!Mh=kl|k>0|+Y=WCRq+IPM9Gii!c9u?5*dMY7L&nj*WmPU2xTqg;{fYn~6Iq8gwy zWW>r2DU$u29vD%OQNBnm>lM^Rnu%P zTQYaLxUmec$=txN<(_^qQEY{0a!l*MQ|N33#f{%QTI_9>=h5Pl*xK1u;?`<$t5_fe zDA*WjSF+=BG~`M)UFpU=kH71Kj73f*M=Artkg2B|E0y@L#x}HoyPfIAe5XrG6fQrJ z>e5{PE`N9GhsFYDl4u?T>iymJ&l2q}-KBM)UnEf|ve3y>UA&gffifad(^6dwznGhK z0EA{N21a*kheU1mRaYPj_?clu*=V$TJw{R!Hpla1(o^hb�tj{tHzeM0Am-L&aHa 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

E=BXjhqb2V@Hlj%5# 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 a?T%_o+ai2|>CL;UHK&$#wY#T2= Config { - use iroha_config::parameters::actual::{Common, Torii}; + use iroha_config::parameters::actual::{Common, Network, Torii}; Config { common: Common { key_pair: self.key_pair.clone(), - p2p_address: self.p2p_address.clone(), + peer_id: PeerId::new(self.p2p_address.clone(), self.key_pair.public_key().clone()), ..config.common }, + network: Network { + address: self.p2p_address.clone(), + ..config.network + }, torii: Torii { address: self.api_address.clone(), ..config.torii diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml index 65d52302204..e5449023aa6 100644 --- a/p2p/Cargo.toml +++ b/p2p/Cargo.toml @@ -16,6 +16,7 @@ iroha_logger = { workspace = true } iroha_crypto = { workspace = true, default-features = true } iroha_data_model = { workspace = true, default-features = true, features = ["transparent_api"] } iroha_primitives = { workspace = true } +iroha_config = { workspace = true } iroha_config_base = { workspace = true } iroha_data_model_derive = { workspace = true } diff --git a/p2p/src/network.rs b/p2p/src/network.rs index c867746b435..ab781dcd626 100644 --- a/p2p/src/network.rs +++ b/p2p/src/network.rs @@ -6,6 +6,7 @@ use std::{ }; use futures::{stream::FuturesUnordered, StreamExt}; +use iroha_config::parameters::actual::Network as Config; use iroha_crypto::{KeyPair, PublicKey}; use iroha_data_model::prelude::PeerId; use iroha_logger::prelude::*; @@ -67,7 +68,13 @@ impl NetworkBaseHandle { /// # Errors /// - If binding to address fail #[log(skip(key_pair))] - pub async fn start(listen_addr: SocketAddr, key_pair: KeyPair) -> Result { + pub async fn start( + key_pair: KeyPair, + Config { + address: listen_addr, + idle_timeout, + }: Config, + ) -> Result { let listener = TcpListener::bind(&listen_addr.to_string()).await?; iroha_logger::info!("Network bound to listener"); let (online_peers_sender, online_peers_receiver) = watch::channel(HashSet::new()); @@ -95,6 +102,7 @@ impl NetworkBaseHandle { service_message_sender, current_conn_id: 0, current_topology: HashMap::new(), + idle_timeout, _key_exchange: core::marker::PhantomData::, _encryptor: core::marker::PhantomData::, }; @@ -192,6 +200,8 @@ struct NetworkBase { /// Current topology /// Bool determines who is responsible for initiating connection current_topology: HashMap, + /// Duration after which terminate connection with idle peer + idle_timeout: Duration, /// Key exchange used by network _key_exchange: core::marker::PhantomData, /// Encryptor used by the network @@ -278,6 +288,7 @@ impl NetworkBase { self.key_pair.clone(), Connection::new(conn_id, stream), service_message_sender, + self.idle_timeout, ); } @@ -341,6 +352,7 @@ impl NetworkBase { self.key_pair.clone(), conn_id, service_message_sender, + self.idle_timeout, ); } @@ -366,6 +378,8 @@ impl NetworkBase { disambiguator, }: Connected, ) { + self.connecting_peers.remove(&connection_id); + if !self.current_topology.contains_key(&peer_id) { iroha_logger::warn!(%peer_id, topology=?self.current_topology, "Peer not present in topology is trying to connect"); return; @@ -395,7 +409,6 @@ impl NetworkBase { }; let _ = peer_message_sender.send(self.peer_message_sender.clone()); self.peers.insert(peer_id.public_key().clone(), ref_peer); - self.connecting_peers.remove(&connection_id); Self::add_online_peer(&self.online_peers_sender, peer_id); } diff --git a/p2p/src/peer.rs b/p2p/src/peer.rs index fd8551cb969..bfa8af93b80 100644 --- a/p2p/src/peer.rs +++ b/p2p/src/peer.rs @@ -12,6 +12,7 @@ use tokio::{ TcpStream, }, sync::{mpsc, oneshot}, + time::Duration, }; use crate::{boilerplate::*, Error}; @@ -38,6 +39,7 @@ pub mod handles { key_pair: KeyPair, connection_id: ConnectionId, service_message_sender: mpsc::Sender>, + idle_timeout: Duration, ) { let peer = state::Connecting { peer_addr, @@ -47,6 +49,7 @@ pub mod handles { let peer = RunPeerArgs { peer, service_message_sender, + idle_timeout, }; tokio::task::spawn(run::run::(peer).in_current_span()); } @@ -57,6 +60,7 @@ pub mod handles { key_pair: KeyPair, connection: Connection, service_message_sender: mpsc::Sender>, + idle_timeout: Duration, ) { let peer = state::ConnectedFrom { peer_addr, @@ -66,6 +70,7 @@ pub mod handles { let peer = RunPeerArgs { peer, service_message_sender, + idle_timeout, }; tokio::task::spawn(run::run::(peer).in_current_span()); } @@ -92,6 +97,8 @@ mod run { //! Module with peer [`run`] function. use iroha_logger::prelude::*; + use parity_scale_codec::Decode; + use tokio::time::Instant; use super::{ cryptographer::Cryptographer, @@ -108,6 +115,7 @@ mod run { RunPeerArgs { peer, service_message_sender, + idle_timeout, }: RunPeerArgs, ) { let conn_id = peer.connection_id(); @@ -118,11 +126,15 @@ mod run { // Insure proper termination from every execution path. async { // Try to do handshake process - let peer = match peer.handshake().await { - Ok(ready) => ready, - Err(error) => { + let peer = match tokio::time::timeout(idle_timeout, peer.handshake()).await { + Ok(Ok(ready)) => ready, + Ok(Err(error)) => { iroha_logger::error!(%error, "Failure during handshake."); return; + }, + Err(_) => { + iroha_logger::error!(timeout=?idle_timeout, "Other peer has been idle during handshake"); + return; } }; @@ -175,8 +187,28 @@ mod run { let mut message_reader = MessageReader::new(read, cryptographer.clone()); let mut message_sender = MessageSender::new(write, cryptographer); + let mut idle_interval = tokio::time::interval_at(Instant::now() + idle_timeout, idle_timeout); + let mut ping_interval = tokio::time::interval_at(Instant::now() + idle_timeout / 2, idle_timeout / 2); + loop { tokio::select! { + _ = ping_interval.tick() => { + iroha_logger::trace!( + ping_period=?ping_interval.period(), + "The connection has been idle, pinging to check if it's alive" + ); + if let Err(error) = message_sender.send_message(Message::::Ping).await { + iroha_logger::error!(%error, "Failed to send ping to peer."); + break; + } + } + _ = idle_interval.tick() => { + iroha_logger::error!( + timeout=?idle_interval.period(), + "Didn't receive anything from the peer within given timeout, abandoning this connection" + ); + break; + } msg = post_receiver.recv() => { let Some(msg) = msg else { iroha_logger::debug!("Peer handle dropped."); @@ -187,7 +219,7 @@ mod run { if post_receiver_len > 100 { iroha_logger::warn!(size=post_receiver_len, "Peer post messages are pilling up"); } - if let Err(error) = message_sender.send_message(msg).await { + if let Err(error) = message_sender.send_message(Message::Data(msg)).await { iroha_logger::error!(%error, "Failed to send message to peer."); break; } @@ -206,12 +238,29 @@ mod run { break; } }; - iroha_logger::trace!("Received peer message"); - let peer_message = PeerMessage(peer_id.clone(), msg); - if peer_message_sender.send(peer_message).await.is_err() { - iroha_logger::error!("Network dropped peer message channel."); - break; - } + match msg { + Message::Ping => { + iroha_logger::trace!("Received peer ping"); + if let Err(error) = message_sender.send_message(Message::::Pong).await { + iroha_logger::error!(%error, "Failed to send message to peer."); + break; + } + }, + Message::Pong => { + iroha_logger::trace!("Received peer pong"); + } + Message::Data(msg) => { + iroha_logger::trace!("Received peer message"); + let peer_message = PeerMessage(peer_id.clone(), msg); + if peer_message_sender.send(peer_message).await.is_err() { + iroha_logger::error!("Network dropped peer message channel."); + break; + } + } + }; + // Reset idle and ping timeout as peer received message from another peer + idle_interval.reset(); + ping_interval.reset(); } else => break, } @@ -229,6 +278,7 @@ mod run { pub(super) struct RunPeerArgs { pub peer: P, pub service_message_sender: mpsc::Sender>, + pub idle_timeout: Duration, } /// Trait for peer stages that might be used as starting point for peer's [`run`] function. @@ -365,6 +415,14 @@ mod run { Ok(()) } } + + /// Either message or ping + #[derive(Encode, Decode, Clone, Debug)] + enum Message { + Data(T), + Ping, + Pong, + } } mod state { diff --git a/p2p/tests/integration/p2p.rs b/p2p/tests/integration/p2p.rs index 9f1ec520c87..74279167f5e 100644 --- a/p2p/tests/integration/p2p.rs +++ b/p2p/tests/integration/p2p.rs @@ -8,6 +8,7 @@ use std::{ }; use futures::{prelude::*, stream::FuturesUnordered, task::AtomicWaker}; +use iroha_config::parameters::actual::Network as Config; use iroha_crypto::KeyPair; use iroha_data_model::prelude::PeerId; use iroha_logger::{prelude::*, test_logger}; @@ -38,9 +39,12 @@ async fn network_create() { let address = socket_addr!(127.0.0.1:12_000); let key_pair = KeyPair::random(); let public_key = key_pair.public_key().clone(); - let network = NetworkHandle::start(address.clone(), key_pair) - .await - .unwrap(); + let idle_timeout = Duration::from_secs(60); + let config = Config { + address: address.clone(), + idle_timeout, + }; + let network = NetworkHandle::start(key_pair, config).await.unwrap(); tokio::time::sleep(delay).await; info!("Connecting to peer..."); @@ -139,6 +143,7 @@ impl TestActor { #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn two_networks() { let delay = Duration::from_millis(300); + let idle_timeout = Duration::from_secs(60); setup_logger(); let key_pair1 = KeyPair::random(); let public_key1 = key_pair1.public_key().clone(); @@ -146,15 +151,19 @@ async fn two_networks() { let public_key2 = key_pair2.public_key().clone(); info!("Starting first network..."); let address1 = socket_addr!(127.0.0.1:12_005); - let mut network1 = NetworkHandle::start(address1.clone(), key_pair1) - .await - .unwrap(); + let config1 = Config { + address: address1.clone(), + idle_timeout, + }; + let mut network1 = NetworkHandle::start(key_pair1, config1).await.unwrap(); info!("Starting second network..."); let address2 = socket_addr!(127.0.0.1:12_010); - let network2 = NetworkHandle::start(address2.clone(), key_pair2) - .await - .unwrap(); + let config2 = Config { + address: address2.clone(), + idle_timeout, + }; + let network2 = NetworkHandle::start(key_pair2, config2).await.unwrap(); let mut messages2 = WaitForN::new(1); let actor2 = TestActor::start(messages2.clone()); @@ -287,7 +296,12 @@ async fn start_network( let actor = TestActor::start(messages); let PeerId { address, .. } = peer.clone(); - let mut network = NetworkHandle::start(address, key_pair).await.unwrap(); + let idle_timeout = Duration::from_secs(60); + let config = Config { + address, + idle_timeout, + }; + let mut network = NetworkHandle::start(key_pair, config).await.unwrap(); network.subscribe_to_peers_messages(actor); let _ = barrier.wait().await;