From 580494fea776315c15473bf1079e84f9561a6246 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Tue, 4 Dec 2018 11:46:01 +0100 Subject: [PATCH 01/18] add correct icon --- .../BTCPayNetworkProvider.Groestlcoin.cs | 2 +- .../imlegacy/groestlcoin-lightning.png | Bin 95340 -> 0 bytes .../imlegacy/groestlcoin-lightning.svg | 54 ++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) delete mode 100644 BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.png create mode 100644 BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.svg diff --git a/BTCPayServer/BTCPayNetworkProvider.Groestlcoin.cs b/BTCPayServer/BTCPayNetworkProvider.Groestlcoin.cs index ce9c7305b..ec63bdfc1 100644 --- a/BTCPayServer/BTCPayNetworkProvider.Groestlcoin.cs +++ b/BTCPayServer/BTCPayNetworkProvider.Groestlcoin.cs @@ -26,7 +26,7 @@ namespace BTCPayServer "GRS_BTC = bittrex(GRS_BTC)" }, CryptoImagePath = "imlegacy/groestlcoin.png", - LightningImagePath = "imlegacy/groestlcoin-lightning.png", + LightningImagePath = "imlegacy/groestlcoin-lightning.svg", DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType), CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("17'") : new KeyPath("1'") }); diff --git a/BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.png b/BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.png deleted file mode 100644 index b15107a8219cb71bdb61117412644213f17b2f1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95340 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

Q=~~lb9FthT_if52nYC(vP+I`lFt1X#7a#IK zqMH7|x9eU1rxD(By!aB8y_Vx8C#uh+PijTjj z#Em_RBr9%inw3K5Fp)Jov!?x#crvJlRB)6ndu?yE>o)bdXDkW`vC~CL!yH9QmYtgd zrMGDRR2{H5ODqawjmkF7O~2RH5$%y)fg0$eU?hd4b9VlQAv5DvR>3c6gJglk1IuF% zO$88G`a7FBr~V2fUt{LP4+3YVqZ-lwPFt;XN4`>;B~?X8#GU=za2 zX?dQJcq3A^$kT+-M=rw;6Z&q&X;e7=FPMdoVQ^I_E_iDfrponTQxBx@0A6C6x${OB zrKC*h&E9K7+$pQa)X8vOl*N~L4^^P(cl#~Z#d?p+OO3<26HC7Qr8s;@d+i5nG#yhT zY8|{-M=bMhbKHvy;2tEyjm|tOg`W)0$OFgi+e4uI;f?d}ZH~EJcH;KY05aAVn#FxY z{88LH5{(QR=Yg71md}-Rvyz>!c)BR346PPxv~#T@t$i`xdZ%=w**KUX;PhNqrqwRe z0;UNxyXu|#s9&z23g@2*!>oGO%Twi7_~m!^)=P|X;|#oJe1$wRZ%RVeOu;!S_MloL zKG{SQQ0)s{ytZWp>7TL8WD$f~T>zZ8>c+mmMxs z$N}MspJ{#fXb651uJsRxL)lF6B$Lm5B6RSB1ev_jWidK@HKPjvgwnHki0`TY?iTxb zm*B{4%^l?064|Aq?=f=PUu#-fT`Qx3@RCZ}60F`8hHTS9oAg$n!A+hcy(EV(aYh() z@gRC_R;c(;fYbfAqckTOuWKnlkfP)@;Z0SfC{|ei6Bd()?ztvAgmAWHf=KDH4n7PRd zQfZWW>3BQGVP{%`;&1nW`4k*g6JAyt{xe2I zfodOIA&7<$Zc(Xs5u99C4L$Z{84kT@mR6(V0!jIfE_~W_sQ8Pm^P%G<1JfZhd+RdR-UC}t&@F=$W8(rsxe&i+e@?gjy_X?F`w zyTDalAU9e~(lMuGQWee0bsp4&`9aMqWnP)Nvf6@llF4AU^!?uXP6c&fyD)eN@OVJ$ zlkl2#?^vfF=kzp%juc$x=KnGMD63%E}IeCmTqu}J7!N>;sXObG=)-FuAs*gpT!+rmL^r&~`iDHKk{I~5ijg1+1TSpl9>`5EY{mm4mItb!mK!7c zvg}4+j~mZmp~f@-i1M;{`aib)H;Vz_X4hk-!otxYq*a|I@UBrx|M+?o$Dx*aWSL zUjHfckT=3o22RQi_VFbjDSRZ3+uvK8xAdl#e{t>sP>v!#WK&$o&^7Tl?nzB2QKw_P zqNNok7Yfk`BE8gb8&D>&CwTO}$;jwWEdq6|(;$OW#H}^>2=PXRCeU@Jq6}NKzhYw_ z=LjT(5SH4{KJJi|0ql>-X@rc%LdotM*JEx^r$A~bGu(y+%qKFsKNa_%aN0ho9`{m1 z@zKQL!omfkSJ&M|-5D#_YZ;aMT-$++Jf2hy&5$CP1z)zF1zvt8I5_o3(^QXRo&r8C zpR;*;w!!KBOlq;>|JkX*c_ha>&`A5KLwhU*q>QU>y{NHiBCK+AO3rUHhrovFP?^oQ z%*>_U0DAAH>2DH0o$p*ML_6RQSbU0INI2C1rrrE!O>nzF@?LfgLyga`sea=jGm)Lw z-mUI&J*O{U(0H_HnD^-Mo0EhuKG?ju4H#eqLhdUE!Bm&j(paunQA=kjLv};M(cteS z0Lv)K-piHv6`*kMcoQ0M8#poP+BXtXqyZw& z2H}mKrSk70t@Hi(KT&ZK)}x!*3Abdzz1j2x>5kQ8%@;4M`Va~Z0hQxU@dZt7y$RF0 ziUbw7(l&dnwcUx0@93v6?(_+*uFwKSOz9_~%x^x~>j!@U)9AGmR%LK?6bv zA6xArs~56M^t*lJVKnsbOS6nz=PK<%6<^lG)oV58=||aAhhv_3;5~r`V*E$%{|w8H zu9R`wnOmdxQA~s~)pEo_h=~*Vip6{j2w9H`OUE3N@_XnajZPyJy6ldXegf9Wp4-P) zrKW^@pv=KQ;BWA(;LVCx7u>+6)2ZIt{Z#6VJ$N6FmUwJ&aHN}SQPvJSdnSyJhPc29 z)#h+D*0Ypz%{{c~prEPY=vhK;_+NAfB4;pAEFE^4-H{W36`EE)&c5a-=mDI=v^MV} znR{VQYQJiGuaABdIN?E(e6EvA6AGeW-|m|Szn*eq2F>~7r{wR;1M15tC25&YI%HLH&v z1Oorq4)o~Gb;^h(na+;m53Ohr6vT?cSL*+h4i>osblRXiKiOlBwU3(%J}dW$R74Gn zNwIS$V2dd^(xaFc7}+{~%PqZ&T85_qia42^do8Dt&~G_zMr0EXX}u)}6v_RuRi<;c zlAi!uD}P+qJ5`#x%9;Dw#03he6qY4M2S|r5Pm4cVeC1s5sgSi=8Eli?k1pq2r$Mg< z49MLTuK$?mpBA9=XkE5QsUuRr`a zwI;}IhP9E+zn3SjFQpqgX~rW*W*+4=whz4MJS$9crG5O)-_ zGD2#rCb#i0&!B_s$WM`qV!!nuroX83EGQ{#zFoiQ){VE{Cetw;XfJ=y1g@U}IX=HV z8tA~|U*7Ij^9aVpFtkT37WA$7F?#LV1^?V073z)KUQM_@8-ljl_2bDnR&j)bOjp?2 zi5;_$xF$LjtTT;~^Vr0H@`%u)s&T`YoJKun64EZ3b!p6gsQl0v=(WGJvEm5H?{0`a z?9`)D4gZQ(=>70r0*9vQRPf#qKY#{f@%~f)2X~(X3Dn0UI!xtuO-M|ZMT>)IOJYGA zi*ABZZ%2GuTweurAaPK=#q}OYo8EmW)Xn9C`C4^;RB^*l?73G!5^4>&PxPiZZS+v)UiGtT7TZ>NQ zI0>1x$F|)`s99(n$5!Ym%>S(Eh3?I=6)NE20edlmdEp<{SkMf>O+eCiV}uEc**;`He@F7Ss&7J04aNcY*z4)HY;G^pc?909+AcaY^dFF0g!N!c3|H(nCC0dOOc zblMovLV%fS-*^l!{LhMUI~xrrdqtx7lM2dt4ktIqGC?Qi(e~g-dV*4&F}f4snt=7? zZ?)=is82|&!^d=8_cc5uE+)_(HrMG$@jok8maJqHavH1NSq@k}tTeD5-nVAGc*L3$ zFEy~h?ugUYh&0|Wek(0h)td1fGhM1k^X|*Hci~}wI)hW<#5P`|dr_W;9xLnXrd(+6 zEhdYDe%0})qk0vnN7H``o|-<;Ga?(yNR`~+!yl~&&Y%`7p@jsRpcCtt+w%V`S($i# z{BZ6)X-}enjOWfn`{~$@m9z(G*f-#}xde+=R&f%FUU|uw&dVKGRvqbtnEn}+YLSn( z;QHTQe!B8U(%^`r!=YSZso#I7FRiTyGoESX z>q+AKu)?%fl(C0X;{V~PPl-P;AY(k6-HOT%t_h1;xJk8j(d`C)h1G5dC5#h7$2q?G zmf|eL@70dveb>ic_O-5dMOL$tB6T=tA;qzq%W~d3w|sSb!ausQ0{t180-?$>X$E3Q zaYJn>JGU0I?;rTa=fcA24LRGX7;8!-hv&wBV?Km1(Z_nJ4DBJ?>9>RYNx8*7$=HnT z_;Fh7@f$zV?9)<>Ic#=ilLxKd_)xv#m&L zQtsD7w6BmG%cyt8KW1Yx;06`&5#ELu;t#Ko0(X~(&b9K;oRIj@S?24yBnh1)M}y4x zS^l4Wet@~mB%k~NJh@-3m)(jsS4MZ`!e)=q`+Thk>?K*!YO&PSI(&e&wY+kabBb0K zV3RN~e<nd@Zsn7zT; znaO%!dmylYPyNRoK0(MVtnR4ZN4v^6jxk6nvGW51xcn7=A{QT7abtGp<^Lp8h$RA@X}-!Ja)7qv2f$o=|ekcxusAw znFNKTQcJNV7N|2ZPt*Yn%VEu0R8% zG>jb|ByVleWo->9UvMrBB%8m3{t_>#4jR3O!lsTCiMk%Ac5nBU^=m?46g9KXcBbf9 zRDG4Ip^?1u$^79f-~XaoJ+3)I9kJ4f9kp$@jTjYNM#nDRAn)7XOKqEF%YFfA9j2aj zTJNH`l*NgNW??v-Hzmr50^M&p%u6M0)OO%=H)ECAFIP6iJM&+MMV#EG-A+_biP}(f zskAlAYl*a2@OHS!gEB$tzF5D#R_}FR0r$>Rtowu>YA3b@pj4EBXd|c&R5~}k-(rf$ zb1My`e&ojEGRH7X)I>CLckO6EKA7CNvHWgp>-2bSG$Nyd9T3efON{SswvFmmq`sDp z*P>Iy1FRy(tADzA@ojvVkq7TgJ`!^Bb>q)OnSFRm=3Fe?{)sLnh2a7NH-L{zQRHQB zCv%2DFzy~bI{PI(Ku(#uOkRP7@2cKld>vdQ6qS=nW&=;X5 zPpV_gadaUFd7xX}wM-!_R#B7xAbz|TjQb-fg^V_bc5+YhlMXr|p>V_G-dp;?Bvu|9 zxAzMQSAK*sVdg>m&n6NVmfAei5?|4id3~X%fK|Uxxs~&zfkU~-QbyG0@c6`4cVFxN zU{_$@|EPuIRVQEkjC{~G{==bWjR;ZSjpus@8SdTn8-BCwU|70T$aH~r_bOGG zbZ7Sb3(sevRhISHLS!KqPrlGW<<^|W=3cjUn+_GKXl2cR4PW+ug)wX@kyl)uwTwBl z&_ZgSl=FBwPvO9IE_eT=?++P>fXSdO{QORBUt5Gt`H*_A`~?3EANJ z;w31&f~qD*0hR01$&swfk+Cr}I*RXvipwwd7k&OmCMGQ6lZs)ok)iO?ZG+v z&Jx;~2rqqNAQwyf!k<%^IA_R{zH-uBf~!t)yrz;3=Y>vKte7T<+I9E;a>nltqLeME zVu}jI9s=UjDHJ!H7TFLHH{5$TaNtLIghgS_K^4!c-=^Y8EMN$lB1H}jYxXk>(uNCf z;;kOS-bGf_LPL@i`-OfJn44eQ$0X`m>8Q*tbw97MZy}XgxVJvjh6u_B8u>VPtG}9( zca*Wuozef!ow1b#B^_(2IGnMJ^-9eFTM_s7Z(}x7Bj0!>ar1$U*-=t?>}LY^Q>3a! z*E0LZxQ?u!IIc-8ENs(1aU)-a3NVTps}BeFdt;ugK8tfxL3p$kK$q8a70@GoUSIPw zd;hdrrMFUcH9=F)9QgxY$dTG>H!!Tc&2<-uxaB!sC&`QY>M$f1K|K@BeW|6+QqEXr z?30c6Ki@X5qxDuZLv&E)%MycP!)|s&&-KHFi&p5pOV-MhO(*wutt-cOz}7PF2ORl= zuQB}T1FUM|wh2vSDEeV^2cgX?X(`XejGWrtmu*|b>c5Fy9PCKcjFB%-`eg~P!8Sf! z?Youf7e}?Tg2oQ71*#N2Aep!#Yp_Tep|IH-ko<4P0m4wF32w-hvhk0;%5RqS7goW z8k=-Jhto3t*i0^~K~}4)o|V@McNi!e9QQda*i9EYscGbGQgCh#rGbZveurdZ`?vSL zuf9Z-#11{HK2xFE_ihohp4Vy-P@6P;7lAK)kH5!QhrfuVzbz9VMs}=jSxmERze-}n z&Nv4QF4vjW?dO^cphfChFH08AuhE%6S*gkBXagn^bNf2K&(1^NLSG9L!5IGmUCjvJ zE$2Sdr74?3;(x}MPFe;UUs>i2>izWuOB`)<-n>cH6-)WDTk0BqpnQR_0p!NmGzYiO z>W#bQT*9WF%k-6$SAB(I>x~_}y`GiqF^kuM4eIkJb|^VPw&ETb4E#HdHan%IOpQ=g5w=^b zjgFJgyR3z?LXp8}3@?f)yIPqvB#VR(TuY&(>>lrMRppS1jjAovrJ8<*CEju2a<`%*a+p_ z4)chq_GBj-BQoWp(X!yW67ql2QjqDcEVz*y7aRx)N-D`V$lX=|xLXjHh%HlzD)$rPj_kCZ`?JuZ9WCYM< zoxG~v&{St?_;ctKT@N;yA z!?G??XTYuJc@&OZx%~o0?d^pvEV-bUeShUhCQ%GYy&1OuwLiwQNO#(C(9%~??MvZ& zE?q^HRQFq`mjmi>dSg^-QCMkoflwh5)Jso|xPI4IYJf8E zR%ZXW5_%Y;?>cab_yvY6MdGsXA(q*F_+Ycw*%)#bz*|!=iXx%*ynVMOdpRvF>Xp6p z4gBqLAb8Q9#`yLA7L#FX%_!346&!z2!!9Y(qv+3N9KL~NH7`GHW zkTgUH@9j?t&L$$vG+k;NFLud=4wp%-A5)>4eeGc`le6h(kTL3li|;UV(w{3Pq`Y)a zj{+t@D(D6FeAf9ql|UlRK+Tf2Q+W_5Et*e&GX; zx)~YNjEO&J<3u}Sg%F3G`~{7Mv)AffYbW-eN3TzIaK(sW?!(>nICA`_=w(R`U z7S24mB4Pf}4H>B&#xlo}2aNOn6j@5q&-4d}2xN5kCd!T4wZVM*Vk@heEB9wZXoGT1 z4a;nd2bW$rd$t^)I<##aj2{>aUzQ7IL&8sz31xXr%tynm&dDG+Xpp4cT8*q$WAxEJ zr@wnz%dc-h&1doTbvrLUl(0|lwK@H`X?-G__k&OkVv^48_z&m-gf38WZ<-ofIS>B*jNc^pS!Yh{Vx zBw1~t6BH_2-b&<`C^WM9SYr9rJbsKGO22%=31rr0&qqNqGIHGmt7=<;Q7?xl@Zg0S zvx6u@rXMx+cs%oG(MI73BAbhIRdBR07nefU8(zFzc=l@Jl`#BbD{aA)LM&QJXs-ix z#k?pz43XS$3MEk~y;#d?9Y1*v8AgeMt@g;%UE|`u^f|WEU=cf(hHK*4?L6GDI0Hk61_7t9{)_eW$}m3~Y!q=m8Y!j=5qjn(KCR~Ze^ ziHl!N%y-`}gu-jVDd)}Y=ULp|oiu!81yb}*_lRGT5#Wu&V8V}S7(%*69pZ*Rqz0TN z9eI!`&M)yWdWAf~B-!7@FlF)6yp@5IPGQAael9RBg$F;IEp%1nu>dxPE~9OKC;CFH zv*d0xW{rZe!$WR>eyUvR)KlH{Fpd_$5_o+WjAtA7P`E0|N*}xINNVz6b#jMiO!6T# z95XkrmHgOEdvhNN_9>5YeQcvS>#3sj?q1;O9iI@RKV+7nvVo>X9hV>f*_9MW0?qE% zl`^+#^3KqHYo_$hqMJjI_|iV}m^5}Q&dbtdcP(FN2##WzV{KWY@C%>Ie7YVa^(CF; zsr{E)Qj#w+D&e$22%)6&<@v%w=lW-^yl^d2G3v?C*Za7pq_CIz9csGeZx>3l=PLk6 zZ71G3e-YjoFF{S>+*V<2ZVQ(Ze%%9ROx>!*^Z)a>k0h`$L8iO4CqrI$F+AR!36&0qau@ud3LE8ML_rv{tvw(xbQ z$s*=xJA>n#OLzUfz_6d?LBEj17yCEoDL;!WGg2EM2zj-ZRtbe8#1eTHJw{ zRByy&z6>F%GH0ydhs)UPbb2kgN$2o3tRwm??3=%4mpa2(!J zudg$(u~$ukQgJe!hqTpa`Js6=o;9oTXZySrf4Zc=TkBaC#03T}o{{3ue#-9h?V5)B zn@)ELg3Kz(&N;6IHO=PS>)8g6tRFJjNJfpTe$aDN|A37a39nFXPrWufYodCoJiz+~ zb$4)OmDj;ZFngbzE*>BCscYLFA2`VqO~aUI|8lBBty3ssU(8ASG@|$t+`S_FVvewoQP1q9yvNYQyER?4xTaVulwLDeu-b5>p1q0tCOKPb`?Wf z*{n3whCPS72ghhG;FL)wrZ}pHnCDroij9X^Td}OHHZqJTw$VB5Ehz$t<9T_iqPan#*u+WKU*c3k~k^e*Vsl(ITm~LAT;h7cE{P z%qp%EgZd0TiP?guJ4N_t5%v^ctdr~V$ihmt8?751&1|2KiN4ww5!_$_dc5TJZu_nb zV^)+9zl4S`1!H2ou!0VRn#*$i`Cj`YG~r6PbKd3d-s}L7o7}mFSx>Y_UF%E=v=3S) zjlgq}aP_g`L)JYi-MgXkGo0mML}q7QVs-JTds=6dcN(Px_+E}_ABnn*Lq|i-Zu`x&S&Aq)8ZEm-K1Zw&mG$Syq-1YBzZ;1<&3E+x7Z?s zm1pD5OErU3S;*)?_eu-+cuHOp`TY3?-0OS9w{*gY(u&RPj=>KJiX~A zs6RaOg?(AtR5~z^hqF6*{L5*gmI%g2@}7%*_sDX~Gx7 zZB@pO{XdzT*jOR6Jzd7iZxfC8QwY;^9 zNi?kA;m3S?=9knjzV1H=?aa5tLeXt#Sip7A{eC^D%i(!AV*9PT404eT>nC<@K%iQ8 z;}+^O)sg5R+Vpm+I*lh>JGW6^m1fH0IZmJg)l)S-vv*Ue=}LMn*b+GmWdE#OjaAz{ z(M%f>_R9^P4f89Py>7I3(DjwQKj@&sog@I1)R7_K4x0hqqJNsI$}>y{loY>X+Af|Z z4a8u;*n2#m02eQ-6<5qY#IY%A(Q>*-o#h+U*tKX@L9xQSSQ%j|t*b8xs(atTw*aA7 zL&y|-fOi6XPovJURrA1j5OHsnR)uP1-oUa+5<9|Jpd+vJ%APdH)}l&%d@x4QcDyf$ zRcp!YV7&!L^J>vjb&%NF#I#u<{-P-plkNR2Q2k0N9KY{8FquCXI_JW7@ru=XNp)D$SH! zKZm5kLxF12UXQ@y8HrE0y-M6MQpQAdbc*vpocU6l{E1@F=%rv`dHW3(x5&eQv=eQ? zH4CHwR)?H)k3c0QRYz)CT8~v;tRa48>2e`F_I1L=fT^5Rv$Vv4@W{B^XR5p~E0ak= zR_-Nm9?`_?B7HiZUzje+~`=ldBVM_YBi0)umK z<>eU@Af){kfwH4SQ7t_@w3#l=^iEsaB3cFw!C;B(BG!&8Ro3Q>)HVk-C`;eOLn!9VxGhRdfYY1>a>=EI=DtYyHKTS}v;r;f28(({I~{}1X2 z_)+`x>Airo?wWle9a^Nl$n;J{?Xd?Vd8mi2wf=GGY)C2s@bw^l?UL`gbS9p-hN9A$ zx!X?k2DFwJ=~q0`3&fxrWadkI*a^n7&VXDE$^f!*2DvK@By)0YK>s(+G=78M_-US- z%z|_^d5bV5?I@!G>I=tBm@nv-hTc>aUt3>Q)frS0aN7m1UlDxYVi(JFCDna`p$-fM z-h0e%++JAeeI9cDRO)ateHfyri3fY^hi^HKgR*pGG*LqLeNeW|ImHiA85plkjif;> zg408n3w?|6z@JKig%P69|@1S3g!O><5ntz7Ius1Sb!h(Jtc;B(XnF@ z9S$JA1e!NdS7Rgpjffu?QQnP-^H!|Y0t*;lJ=s&F77)=#ZQE{r8iKFmXmV8%y4lAU|im05EpJfl$-vd zE2S$&-S>D(+!c%-rK60A_b8c_((%r=++h@MRJ*pbId&8J);eg{e-pC%z&YAo%f`wR zWEMPo@${ZS5kA|^`zyP@GAg$8(@P^kow=HVO!04`blT^~>vzyQ1eyI(yBfi3T~5)$ z3hdxpG`c#Y{L_UdPMi1>meut9CA(uDRnH+U069c@5?_;O@Kh zUnM6}@%q-omW_mWpMD-m<;?Wp1>6{ckj_f0-B7FWX3WE>#q5>kZU5Na%Ty#;^|<`^ zxQShvKtZehBn4T9iObcIB90;3(eOraSe(hr*S8Kl@^dWyZ&N~lXhGqghP^ir`PNMI~T-dQZBpGH|>>s_lvPNqze!xdgt_T<>}o5G3}Z1?x`L zvMhhNZ^z~uhZa}U7fCQ^q4N(MyOjt&w0q&#mpX*pgAUb%s-`)>H$d>wwvze?@2$ap zKUT4Ck08)}v*m>Sl#T1nBad4_s(I|puk42%u7C!nl8o0KGWP~{@oRt!ClaRf^|@)L zf7dZ!@Hi-MHZnZ0{>d+bQy~xSm*3je&#Js{jx1g)>Gx*=YeP?)W6R0Jx{;7VipTez zSJvgAhHLu~)~t~u^T5wReW7)cB&eCVA7(3go3!cFoTH|00YRks)~#Ajqn{-1k|;2o zbK$n7fv^eHQmePy?zT0#Am%G**=%ttbTqLX+Df_VLMqt!r0-eWL2{+E&6MCjNRfzw zub4Hzg3Dpx#oJ4ayLPe!OI^~CaW*!1lwy0w`z-I3Tb0~KPzVCyg1W&TQbbPka4^s2 z_`u8E2mAh+ShU!qqc+ZkL4(YaB8fcvQ$7>Xb!r>CT`}ks=>8Ky^hd_lL-gXqSt`&= zPufvP*-3Zb-KWQ6?f3)7Uv*Jegv~)gIOeiQLyU_8i<#wKBhuM59&~TiPJ4jCptlbz z7e^mtNd(x%UP9vi*c@*&@3DdF{JlsNzs$VXN`BVZU^1Yb{=xqDA$*d`o18Gu;(_9 zLh)0Qs73{0?nVkXfuh9R08Jqm#qtRMC>}=1XdH1T509?P8i$Y zfn*}{8!l1d6|5k;QLI~Psq~;ZLSVIJB}l%cOxIlqYNDk&#K9_aR4#S67(3s$^*YYjga;`*7hb3d zJJR3x;#HrY-yVXdm%eS8`jDxb)n5J4imUnHTess<8TwY%srx`Py4*+OguiLopofWu zir@1J;vCrgyuClC`ar({x>xjM=UGVnNaTTy{_c9PTSM97L#`JG*@Wvie;>ghh%*r5 z(P1q)o(!{ku*g0ptF~CY<17Zv-w{{I9v-jAFI#vxekywjIdI;6Ue>(G_yll36kNct zz7u}Nx7G**dv)VYcoUi^K*(}7h#@)i#1a0dkRi?U_-nJZ-Sxo-8O(HJ`NQA(6ngEp zia>?#qs3!FDHmD1viK}sd1W~U$(Os24S)fkpnd?D1wH!BBR3FebSRTw!7W{| z6yYYaP7!P#y0h1QSZuBf@uQm-9o@G~%~uF^$%|~34VK#W5A+PG=&Q)7P>5D`VI&?g z@n_Fxdg|}!#0Pad*7mS38f=L~eM*dhAK*vETlbSB48EFPf-#rWubYv z)!bVS9d6!_uhySJ^raMUNoPsy4&cP+gqyP&q@c%y#yA135@QG&ZYLiW*MiTy*0-z? z>@e{IaMNMqoT>y)CAj}MN+4$4jBNAuceDL=XM}KGtH_!xkOqV}<=}fIc+yn(bceGP zw<%B9$r~?lNDl;Yw->6x`!&X&(Nr9W6GvKh^C2A^%b_5N*%hCT% z^uwC3Nj`_}9$%XFpX2fUuPe{)he=dGG&Hb?$8(CZ#59LhcN7oLv6x4iabs^XiJ|LA z219SX%eSl=a-Y3n&w3N&`GvKzG8-X`(h_6@J(?!ri~P& z0>^mrYW?LXXv-W)IE{MGeB=Z5#2}UNgoS-$JV5$`)w3Xz1M2>5uXi=xM3_JL?gqac3Gq1PqWeulMq0-VVP?`vAA7d)n zbl+dQ(s6WW8jw6@sjb$DFL?@y?+!ti3sSdlLdeO=4$vVL)56c_Jh!j zyzOh5ZH9>Wkv86AI~M%VC?V}IzK9=}BCgS4yAiOwcm^|yWYAMu7_0DiE8DvcQEoKx zP;U;V3p{C<&m9x+uHgkn>DLehU%&Z| zedPE{Vbt+p;i3(C?_w)gIc?(X0mMhvnVWRWE-LSX}UhAD38m=?AJ6^fn#?9ET_CBqEEaaNdNiwllKh}jMFq{?o%sAh5 zki?E7&3i(!0rC}}LqGG80yT6=>-p8Q&VkEm;?W&_7(E%%CCDXkhRj#YYwh|?Vo00} zs5dMUoex*_(Ru{^TK`AXl?Oukef^P2MF?3UDnez8gp8p@lI<(0WDD7nWg6Sql}HMy ztiy=VB0|}>vSyjF6xnxU-v-lI-}^i>e(%4Q``ml(x#xV&=bU?P^z+S9zlxWTl7r^y z_CE(MM;rwCqXzN-n|4F*ln7qqq~#;$!O-~@4c)!;uFPaj)J!ebuq?sWa3RH|eFi*k zWPa$6*Si4aoba-3AR`-9sWeH`9NezD)d=HRX zG`vIRcy^4h&jq&6K;EjJAM0wU-OC52uFh|+hrdzB(gqF(J*AV^TiL=FAEPDGE_nJR z=k)M@)p2tJK@j;0v~%)hzpvo*ezk})`aV*21^1S&HPGu1$RANnS*JZ$+Iif&xlV=| z2z71yJEFVilJ` zKd;>Z^yVR`KOvhFkMrVB=e2!SGEFcmj;tE+a`3n2x_tng#fTnWP?EQjpiJSIkT@9? zuo_mt_J#wTn)D-tI>8StyDyy-9Y(sVWqWVDWkH=_L4V+Aj_4bBmU+2&b7dmj&?Uil~FEuCxk%7e_#vu06WdQ|EU&W zj*jUMQ&$=J^qDTCxG(!mDK7_b)xfTklVpIslU^l-?{m!(DjmR{lP#xqFum2kdkXl? z-Zy6-Tp9#54;G{;F!uU@kMwI;H^9JtI%nho49s`M1)|E1dbRK>KZZdqXnFA~M8%If z70eP+#`Um!cAC%bq2Q`g%GVpfEf#&W@^Kk>l_F>!!1KaNGa*uTp}xEd6p#Y>K8KY3 zYUrE)w5zdA0cQLwdP^d;Glx&yMo7`k-7nNkcbDAS`QLAvhi^(=*j!H#8igRS>g1GS& zyydj9Cd+1PuMa8^`zlnrqg7`WAOkBYTbluhX@!H~=N`@4{QBFMU6!B$@N7Z@xDx59 z$a@-~&DXihK>=oze`od}+M0Xctp|zIQylo2D#0=zx70?PGlS>AWQpDyjFvz5L03tu zc}HTl7Q9fMPSFqfZg}~7CxdIiV8i|ZxuSHW!+)rWlBXw=oKK7&Cb3)XY+u`5cf?c0L z1CN1$1NSqi*Z?7X6g#jyVe-Y}xz%}*8SrpA*k@?1VryTa{DD`^gG7UG6K-Gq3yVOZ zupadwRF-}w96dv+SnhRz2L9wd@b@+Z>$PwZ+~;2)P4|TW;eP#SwR?F2$TmoP_j}83 zx~bO_2TTf4>TXx8O~GOGbMCUa0dGa$24{B2_V9va@YBqP3HR zx;WYQhk4#-xWxvM_b05qfKQ+Vq6nZg-tA4AXhO;D8K(~!D3 zI%qf#xSsr@cH;kjy(N7k6`3A3nQlJQGv;beUBJkdW)!Q$8mbz9L_l4F^}wS}0p{&A zl!fuLZ_wzP)Iq@C-n|fuf)(F!BUVH>(0i{YM&jqi-Ebi;8CRQ$q4hena6du91V(+RMY_R#p#;-ro++uKk8OlYCe0OFn8&{!ZJu zx~FQe$0=m7`MXwbWlH?ctTI~)9>G>ZK4lC z3P;KXSFKlTIEvYgEUH`pd$GUk!U44ikh-~d=h@FfC$(oV;TQz$%;KPz-fQr9xYGBR zPR<@HZb2*%n9_{EAX=VQZmz8Rnviw$uv5WjN~KDmR;AD$q^_=Kl>cX9;vy)Yd^;W# z^epJ?ouDzs4a22biUS2X`K7^_?g>iERxJ!0_uw?vIvmzdpJX5Gc6KUqx=m%1Qq6$6 zEx_ZgtfO?!K*_05zU)yyaQ#p8Pp4unGjBKM%X=;&-eaIb&MEt=8V8y&A64u^gT ziHAGl7y{P>>gU&HhN9iGw#GeTZ1t%#8#o!DTaeOgj8GWk&3OA(EZUe)t@^CTWSwF> znrd!&y9v70Bl;*%5oQgMX=uNZ(og+U;2~FB!_|st3v&Z=nM?qgv7Z38++M?MvN$m` z=`rApvn$?1_ut^TFRlw!{AbdOM&%nRZ$2F+>|TBZa@N=WRy~>#45yoHG3-}U!-bKs zsdKtkR_z^^B_YiF2&@kD{O_&X8_ZvHSf=8zwR+z9<^-i3?P%Y8a_;hdhhP`bOSqla zdss~xywDB8s4FO4uif;9OFrNH?-nIXwp&P#aGgJ|Qdsd0%IFw?H)po2NF|fK2kxYX zpnTDlS)a!J@?pcFX9t2a)~93u`7~dsC?&@vK>L?8w+kfRAj-dC1lcpmzP&!99)~Ng zO%HHdo|)%=1R3qq;NS@QZQE&rW&piMV$HL947dEHG9Bb+^B|R}#@>L4CJRZ`;_RyT zJRC2DC!ia+yWfk`Zz-z&c~ap^XtM#R>Cx1Y1R&?5(8XBDxXd^5;C8}VlMP7vz&yrba5ehxnDh{s|jkCoAcgGazFGm2lw@OemNCH9v| zblI=>z3PC%Jv~G4o#_A`fM$?M)S%^dgvu(|1ruU{|76m+ z77c4>LBh%8ptL5~Vu31|t|t{9bGf31`kr3iEZ(55;4JuB2Dn)%(1qcTG_I@YrJDpdGva3<=#L@HwCsV+|DmY+SnkzZ>^{mWL-tkUT(mHn z;JFZr_6PFEJc0P25kFT-@mMn`54b7sUe=2CfoPCWa;u;x#pUDivFRGk3|1=YlV#N%DzzmbjC9ZAPp8o{ABb|`YEapFd`(BZVA7m|6lH(j0|=}EfK z77h2&qS`T-*5QwID;HXS)egry6(<7(1JyS9d}1RzSg9#6k%S6XMFPy6xPdIh?@Q5l z3jZ&4KCvKE)9}qXf}T}RnB-A)SY+F2LZwu{vjr?2lRvwk#~V?VEOsV{l=#4p1u>O$ zN0NBUw4i_2!DB=TaAEaMJrX{*IPh#}Du4t&PJV8uGSYK&I4vjY13F=yq?&u>yi*bT zz+cvT>5ga*n*y%=5_FdyfS$J@PhEwHK$vPtqzYZXlO8K?QlJQtJz5NKyO3TbeFD0% zUE-ym_eq=&7gL*W#VA|{1H5fd5cDXw$W%)Pxpm7p+l*=4b_MDR6;^@bvU64SuQ;A- z0?6S-tqznrL~1WYq0}lOg(~O@n*?5s?z-9g-PK(x<9&{^hOwTj#~m;y&{jRdb$)IW z`K0dBsetJUDbxSWmKu@#jrxrlt(Kow6#?Aan2u^dw%8wv`^$KBqftH%)*K#>S|lYRd%a*3SzcpGU1q^ZfqK zPJ3faZ}kU*4l%6lx;)^0eji#^L~QnzkDh6nvI$=IxJsai2FJBDk-c++-g{W1VjuPP&4)i35q}pPf9Y6R)TLtUwBnu|!_5A)KdXs} z)J=<1Xp@t(GlZGB^%c*B!NAt=ap7hk_oVnPKJ!QFaTQNPlBxEN+aDss2B6CJNX5Q&lcg0oQSu zOHiX&#J|%v-9Nlx4h{FbHXQv3DxwtL5ZUwHR8Nf_+F3z7DV%;<7GZ_@sWyzQqo2mADP zW?D#XiAHI%`ygkUjJwBMHEBs3CNnS@&zwB}X9mG#7rZsC5;Y7Viw+sHu5#yE`DW+i z1lxnIucdq9d!!{k@-qzMIAKRn853a?J$&4D>xka_z3s(tghQ2xrk1$%JjTh-ycOR! zmk?ppO7BRF>gg0~^WLSBt;lrm<|y9;X8Y;MmzyTT05B(J^y@O5vbTH-EOR?*f)&|4T*b zQ{Zq`WFgUV(i|=**Cni@2M& zo5aMlmP0{iBNl|G$G4fa_`Lr&K~_=}!pFznYM(^5BX67w?AlQ4)>~MEkovePzs>ej z8Y?j6r;8(wuS~v}D_|!f236+<{6Eg{OduM*R2SLseqvP&#pr^wJ~=EP<6?p7i#`3^ z8rjt3oN!f?mVqSt#d$dY{gI*l_v_~flPS(U^cRIUk|%@Ty_e++QCA$u_(9q2CC=pC zo_QNtye{1F3?5PwV1{y^6Rl)Q)$+o@U;}P);fg)R|Y1`7QmgpPj-~W4PoW-(&U|gI$^CYGSLe*e`^Gp+WYaNb5gY5@{ zDSKX@42C&4avOj#K697DGCb|#wu>`T(C|u0{pR_u3z&)XO~ z)D5$Wd=GIJo04(YIDnw6jD|}^(5$@IY+dn1(@G?sH*tt%0RbdK%ZoUzUf3W?%i|bJ zOZ)C7>nXuf#Scsi^|y@;Nmy106a`ihG)ENR>WiL!Qd#Ny;T z>tLnVf3vl2ecNe8#bm5@;tN*dC)JF5;ONBh&meRN_3Z~v6tXQhz;$_(f)wnFkf@ID z7}-zbw#pDGHY_l*_M;U|5Lx})FzuANQY25eMU0Yi@2rvB;N0{V{F5Lileobf8s}WI zPb$-HJ4SQyln8HPzTz}pLw2}<{rxndt+9$3#Tq??S*A5MqvBaG&)DT zL{ufH-dpSo6#RC8RGH-A0=wMOH!gmzhT?NkY1aic?i!p+)1guMebe~fR@1#Ujaev5 zBYGBOLv8y_!+j)q9hE-I|HGG|&-O5omvz$!hX*`wWvlT@UU)ADPA82)Zdv+LCmkTtuyu!atwzvmq2+xEckUnn< zi)Wa_t|4%?IZ1iHPHEmbvb4DPpko(}@8>id=uoa!J>UIJi_M--lz^3hIxemor>7Ig z{OpSUDgeQw2+1TNAo#!`SaV9hxv(-S=DmAhg23I2mgmxX1|JmL?KRScwcdOAGmpoZ z4XTwQtby2l{HSlUcW{L&Fku4foQ5X@Io%LAQwb^Bzlgt@TJU|$zn&122>u>3gy5atcq zgPzi$FLtGo&L0l8qhB149k~tfJ8^3zK|>T*Y*DTF`L8r^g>?!y)pv&6y8eJKMjc!w zT`8R3y5Y+<5inG604!COg$JHXS_mdX;$1%}iv-Q^DkrUbP*;VS0?V?FI`!s(1oy4n z@mA^_0hR%e0)c^XzYh6M5IJt6gyAUI0Kfm}8~Fxoq`~wVvE6E87O6FA5zV-Zun>?v z=UKwjls^B>Yv+*{A>}E>$TxOUtdc#7(G_n9ez3e109!b0E3iBS=Pdq_ zv?G|+Ux?5RXhJ@EW+V+iaqTC7|za*R+bMQ%Y~^Zrxk%0 zbm@wIZt|hvW+KS6uKOl4N-cX-2`i28)bw zhrofL9VJ2qI!&;WNdZc}ISwAl-kCp@Skwl{a)7Y`I>aLnNFi&txcbZL%7~+`mF+Li(k~5Dlgw>+gERSq?;ir{Qxt03 zLQ=rKS9MvXAw^5D?Eon}dJ*z$RosfVSW_8=hHi$ms~a4Nx@+@B?uCkSdCmoO2zCI& zlr63GfG@9265Z?JfBbp<+Fo>*j$k~)|BoeLaJbF$ znO#JRy-wpA4>&lW>dCB3`N%lZw*6D-+-bQCCU`r-7=acNCO)Yv;(rOB_}ti&ryAM0 zT6~e#6|V-Wx4Jb>T>5l0dixplh96!lA*4=3##r>gQ0va})lE78B_)!_7j0(kC?6r4G0@PuqJh00Kpa7~T$obq*X?i9FS0 z5)(j?NhCg3GV3VGcQ4I%KCV(?0UFS8<)X}DYdFmnt$%3`ey1-@Vq16j)S+_0CJU_b z{2vN>Nzq@CDV>b z?kTK#(7*}nEhovl%atfML9I~=nv|P(pj$pEQE~2xQWDK-mEJ?64!ZXL=(}3e2A(J5 zBnhPcYCIRP=y{{XRfWZ-@z%|^eB?N~V9bDtwxN73Ap_RarD=%6Ls)EDA!Fx&oFile zCXK#(*C$K>fmrX0<_8kd0wfz81%@n5v zl183SM4k92gRua7E12` zo-aBKOob?3g8_D|rS%{$pe*(;RIo%eEM*|Ao-PWZf0m{STcAc#6O5RNEVh0n|JZR_;dvUka`IP6X>2^mav=KV?j7wY z*?w&yFtK+^2}nfT8=+DGoTx8Rl^w>?W{|Vn3i-7>Ht!mO4n@rH^i z{`#92+4ynC67@3ySbCIHS?mOp2;(H}0p4uihv(IoFL|duOF?Gyz@I~X-kWZ@ z%l3$OdP5Zb;T0dEY_XK>x&ixmMSrf{9NRr7W*M3_;sb}S8P?0##Q!+7yUGs66cVk+CY!K(gP~$1+UdHl z@A9PUG(&7(0+c1=B$0P}z3`9yhV~2jH0Ibdm?Hsx$}_=B2Ki|AE1zAQ#u8{<4?DEG zQ;rpSD%w>%W~F%rfifO8ZS|w~@|(Xj+%?NT2;)k?1vI+xNY)g+8cC#q;vVg8-8f1} zo`aMT+|59dSmT`&IAn*T^nXQP%n+vcf+_drtBPGIyWCVuWeS8f8U&YB)JpLBg?n>e zh1@lGeYRyN;hf#h9JV73y}C3k0-83sR>l4??ZpI=`I1XAe-^P`!$EXg=|40p<3jVQ z?4@YRC02RZa~4s-Sqh2{WDo(WFBkEN1}gyXBY9hqX^`U!5|hOrTn$JNF+vzX>B-kq z2$wH;0|cmP1(&)QG4^O$8$F90> z*)={dRR`0M3$xXr;+O|VJT#$Hsie&ZWg38nDK+k$5X`{F48SL>{PyBG)yHOcVBY2uYyEVDjD%7{bSSwtw*Pa74DkINy54FtI&YJlaDxQrX(8y3lv;P ziCS_q@|GGmfcIt=_|Vwv_8Tn4I-GlcOh%4R(By2}w;rRPH~a_*|9_3*)r;(|AV@>( zr>_&)sW`A_`5fEALzAbCXV-1t!OKBqTpii}H1CBOMekg?u?*VzLK;v!oQ@~TCJJXy^=Iq{Mvq=d6a_Rd#Xbc%9n(m1nlG=)o3JFfg7 zVJH&2CO6T6Q{ow4dr3p|*KouQgR2T0NP%y*%?!>oZz>S}sw?--X-RlM!r8gSr$xLI z56zRfzLaK~?w0L32$gh(k}m;p`ra+kwq^Ffaxw@s;U$`f_QjYP8 zvbpL?4-mo8297v#_i+OxC+$fhruB@%=;JMp-6@gM@VUl1)yB4*>#ylc*QutULwsq2 zc)iFKPyg~$Dd3Ib^n7Fq|4%-6`8>cU9(!kfPLQ=bPqdc2k7 z?+!Jby&HnL2bMiam8ciM@w2lnZ_<_ypi|{F2;qI(i`RewN$+@tmW`KiYawLsgU-|` zz82qS54crrRVEe3!vrlGnCb>`rVN+X1SGMyP8m>M9E?}``^ZZj)m@Ma+J8G7-KjbW zC>q3YiHc405nR~1*KeAGR}TR_HzGu?fJw_moMwV2B1X{q^6HKWq#Yboc~m4g<+;qAXyg@{**37VXTNo=e>G>;TC6C2ZP&r+@$?d8-2iPvMuJ{imX zIuLFIF~LA{x|~o&{%&A^eHWA_xO>@k10vznB4pDMM_(UOVB0_2bI9-=O&!Li4Wf4+ z=nt-G?}mdd5SlPOJiV{@DGb`hKn#g^=Iuv^{wbh(>l^1p{#;ALe>5(f9K+|T*mf`9 z;dI<}c;~MJ@+h6jrwMp9%I_?#-Y;Hnx=}PciaiU~CHmTaBKXjrJnP2B%}ag-l0e&} z{cv*Y=VcB9f)DPYGS9I527Df&6BPKyP;p>A1U5U^oME5wnxUIsk3*iWX7-cN#`%sg z#v?5C5<+288Jc@kHFj5D>8y&>u4mxj-lOb*dw>D%$$)&&*OsI`xCbCTKpi*_TXS3P zZ&vqjwaPtR9J;Srbt0f3neVajDt|3efRA{}1g@mlc=Ak!jrXb)m__`F7hDD=6j=VbENknSswE z3F`aMF&G;HX5^@@E&~(4*sQwxnU?4wG_4~iz_*&i5`jtlxcObhU+Vz(0y0ODZ0;Gb zy�`B_X~#-Tz4hcz^YsFX{mx;6d-~hqWKBbHq92u`vDux1E%vd(OZ{bx$DpU-j1b z*LCweJPg&4e$=x^!E=e(ORzvBXo#5(DxCz4opfjolZ%S1mX!~`%nK`v*A~&R*_?*u zTq*+O@!XXiVp8WBRGg;R9)+8Knwe+00DlEKvDa)|tJ}I|*w|)`v|4z;6^^UJy}f6H zajg9U?KUggy6W_EOv(KyK1LZ`>_1tZ|Cy-GP#?SW1XmX`N2ar&VH~9SqrB>t7Ba@; zw?7h&7)wR~J+DQl7L+i8W|`7}G(C%K>kr!W=w@cei@=M-*|WL1?HZ?pOC z#zv(t)5APKd|$lyzG9GrVV*eKUNI?9ev>0;H!LrBoHS>V`l`$8?mnj0pc)$F=rKUX zx<-5RZcpzG-pSIHNUL!L1wDnv&^M@o-e`QGTm2eDF_2}X&M`+;_a#Y1`-9j)tl2g|Fy{cN1T>bwR1DGdnF&Du z)2UX-S4RddQdArkyc;IS2j`Le%XPVb6!oZ?LofKL!CswnYVP%rbfj&J!Ch)6*g z1%CyrIp~xAQuy^*z*0T4Ozs$oAJC!oI31WaZ!pn)B^Ty}kgB z3*Ml<82%n*BcqE^MWf*GS=N7i%Ns)iGRNkr60Wql0B6y1L1s$9GgYx?^;LR&7k$B0 z2J`XAlhU?_z28rId9F_c!DkxqRwUJ5QL!@AkPDrL3Ef903?Ng$b@3Su06`$Ax60~Y4gBJKiv z^xvN2G>pMsBvEyYaW(b6FY_bKXZ-wC=Fly7OiVs#Dm zCZNlCT7;oV;ZoRXha3>}2tAKga;_df1+0+98{~QCeOM^Gfzz33Z=ZMHLx9GOFpx{%d6id>$~5koKT^rfQ;{Tl>tS(*?v=w$k^=@@F%6ufqf*nXoshN zXAqR@&WkwzXCG~m3WV`wX;z!Ct0{~9zpmW)pJHipaikoZ;2skAJDWaR!sz?+0Iq^^ z`Nxl>r!+-9JLEHtH=E>(AGSzUG3H(F(0okuT-+lM53EIj1-CNKs_ciC6H4}FG<^|Q z%7O9qkL%@WsevoJZp*Ut^)x7Sr&^#<(T^oRH*URc~@AyUc`LiLH$Yr*cX z!gM@dt{3Kqn84O4$p9`3TS*1YGvJlPfRdcSS4UM2BOiWq=8<^73*!Kvt;UDT-dG+F z@B7H|w6YT=vov6737orl3a`BV$?^3q*?j5b5CCALl7(rDvj_9ro3bB^d^I(eld2O~ z{=Ri1&mVlo?1W+n!|y$%Cu}*U`JY$2hu3lpZxk@nbR0DMKBjd8yjRayiIPU+0k?t} zWUrZ#P<(x7z$&4q9bN~>18KcowP@WK z@~Ke6e?35wL4=53q3xmy7}{B3PMkE9s$y{RtgD@MJ+AHwFhAH(Fk>IqKaFwKYjao! z2l@j9)U8MLQB*a2&w3++6uJNbO~{>o$MfV9V2wXvlC>3BlGF?Ad8F-+&?Gk3=vvRg zrO$%q&N<&FlR})GV1?BWmyxk|4_H-pev?ZAX$XY^@O|(*C{!9NmluqZ4!ANM=PA1N8T018fnEKx04Y1h* z9MYknH+IKpSlu4zSeSoBPTwzR!2534?}h7RI;-+Wi|yk9UG(0Z@`3W4Upw4D#g&WK zK1bar=%7iIttk7=HQOq02H#>d2*=v{Bkt1ZMlNtr{d;?js=%nCVUM>9yPu20OTerb z9ldKvh?u*B->Oqk=%iamp+UtuTpo$+?;rQCQivs&so0`Brm@7Il|~Uq0e`owG4jY? zq`$^W)7!n~`8X&;1KUel#VCI(M*ixm>MpLWG8Ohlne8wU1$*kFc-2{NIkKKnbU&6H z0mXg)_0xAI4dk)>@+_DlL>;?pw0N4f3ZU#D5aK;etlHp=g(G-ESDk)PRa;~YH4gxq zRW8s8B>pRpA26Vu22lV{RK0DDkFtr)8e!@?M?J)uwk2Wnxn=h9qR{*o3&&dG-Of(< zN4hv6I|f#xcv;M!@tnu0OuN=RS@YwK{EIGgJzD5whL^+40BrbKK10vA5*1DawJnV~ z7~V+yCQ)+m<{3rrJDr43m)muJ-_vclU-BNs``Cs|!vxX+!3CDJ53s_B2RCo@!5-60 zQ4t>+Q`A%Nna%hdt^RIi3w^OZBlPj$aFd0p$9G3Ax~j0{BVta3G~f9yaccqiraB0T z6_S|g&Se(~A&n`(2-$x+#R(r2{GX-pkDud5GcD}bh<6o!!=D3dd>H3s829*8No(nC zXc!GJjLfEl>#?{^3QQK1vZGmNikr%m1!hNc(l#H}-=K!@f1;I72>D<^4wK9`!M!?H z@2N3g{RZaBz)jp_>*tRnZ=5_8x9Rle&w;sZ7Ox(8+q9fI%-^M_WJ)9|hDZy&&2B2< zC;bO{Qx+E5lKNamqb|a7Wh*Zo;di)!JDWMpBwap9uZ&dvD|=Xz#kPXq`uk&pFXr11 zy(-iOVg?~J``>Ph2U`Ph-%Ro)z?W{!%z8K+Joe+V_PX0-?o(P?5{!EJ(?L&lR;iW)Bq%@RB9*oW z-kzF&lDBK^8MNgg;@a>@GAjn_S2b2xSiEw6Hcvx(8a|Fb+wvj1>_JYWxO}B4p8h}~ zxohLK)+;d*r9^ht*CpS!~k{jtq!VnkU=QWWu$EiVs^-rL5{?kbH^gb4+#J@7xSRh8MD z&Lq=F$2)K9y1sprkSXB52OHKwfxRwk!@)AP2OQQ~&p12KjdY%AdfhwSrdbc`we>+0 zDKw~WU{E_86eK>g_<>eP0Sc|;q_+qT)BFfKr=8 zVr5bMir}%TbGr%>znDSL!-$Rl|pAdoV^STU_h<I_XV{}>-6EakzdmM-sD~0 znm)qjQQE39L05VFtZd@*b56%W@aiI^CItIWu2r{GP{jgz)`)jarhtus2;WtmtVS&l;1oSs85t#Oj z9Ou7f)-&#Lp8$nbPvuU>v zBM{^s;ag_-?1DPD{1q`l*9io>j>Avq^AAaKt&V?htNK*aU`)x@*}i{+(NiUqy$M;Q~SqJ`&yU)4ryZ3KJ;`4I>nW54IAs!K1`DNvDDqL z*0ATTlPz@Gw7`957edsYR3^oIOC|Bd*1B!VSi#QLke2SMM~m*hSYLC1kk*C2=v*>B zvpYZ&_`%ng*=ymA5F^+gc_uoV(d}J=ReX@WTa7y0a2P6$Gn)bippn%WNiaHIu{m(Y zS*NyrCwYW3n~oeshoMnjYb!)in}f@fEBv&LdWyzWz+JLQPf@km$nC3_%Wd`C7o1Fs zEA2;uAwpu||b)`1}V?>fPRovyb zg><%d6<+#NXKqFZohZCxAL+k3+GxoNQDz2y0c4XPW3G(dYP6Wns<$kE>ku0;r6-&7 z$S3aKo+gmUVom^1I+Yr&<04vbUP4F`tHwDq!MqR8QG)u#79^|uL!hGAq>J;7YfP~< z*O>#}Js(zt(TKoElJEFOd3hxAyJDkqc|R_*P$ z%TtIq;n`1!_?Z2?hznHFs`;%ENj;(&QK!yk^Z;xJY6}4SfN*J8;$7`iI=h`kcgxn0Wy#<?((s$9l(~>XDt~2HN&?n7kNyM( zGQqKL-u1Vl}9G7+88A<@KpH7F!&)!rVPJQlR}34*LpvTqPmcQk3#48Pv7a&X?$M@s{G$`fcg zG~18$Roo-Jl@|qV{nP-)_IBr}{7M61FCf{17S8k8L!LL*TKSD1`G4d{Fi=HOs{J4@ z?~dzaLUyMtsmW3P_1f@WGhbQPn5LhdyuJ?8=TRj@Jkd$&2+#&n6d7nk9~9Ifqt4NY zZGeil#+;ocwC&=0x76P>f3%uD&ExywlLQoC)qp#e|2EJzk=&M=H!IYkJzuKP>jiI%WFJ-V80Q2I;6Nj zz-+&>JDjs0;$x=Of~08#a}g zw{DE5*i9>-6q4jyY|m_(Y;pKTDZc5Wz*8vwi$=9K>y>unI#%`z_IHa8Da7C|Ktt4k zCKZKK3u#rXMxO@f5=+Y0XS!dl=4e7$UWl*EEa1W$$dg#sHb^O1T|TW31Iyb_Lw60M zud){3q&aa=q$v{(-Zb+meoH)=uOD(Nm^-nr4K5F_3Bd4HRwVg7jP-V(JA!-eKCrcX z<|SAZ^qRJ4c^a=@hTJ-TwKXNl@^p(bbfW7YN8Z|F0mC9-`_4CROd1=1R*2C4MwaPB zZLSSRXz!!;Lc}*xL(%-kA#KU*(+)#si3u!>lNkTSn57p`(-Y_zCgkgW644Qlip^&y zaWkm!R8&vmQWWX<9@S%Q=DD4Ba4$Pkp1K=~_?SQZ?)f({j!?!A1Db^W>$b0Re?mkN zjZ}T8&E*B&A-(iT+ho1gdK=s%NI>4IM?&Y1z#9OueF#BK0s3|W%;WJw@8f{4TOyTM ze4nhkfTD;fT0_MU%-keF!?RgR50q5BlTw3E$e2T--+OT{rw6* zo?q_Z1k+*vaA0WtjE?M#-YDzrz4)c}hg~Uu6F0E#QzaSMGmtyJ1j5M;vPQ&YwEEe~ zG9|GDi>Vj*-rH%D5G4&Uypwgg3^ACNVaifgm!HL|8j%r1mtvYDCuqq50I+6d<$?pr zbH3@l2#^z*2&)siWi;=R0gOaxi%ZtE6I+YI8YP81q;%)amGAEkK1qcF6NstJi?CL| zcx@dQj+P64U2~v$Eqxlp;1vQHCI%TGcX|a8D#p58UU6!R*xA7r&~-wez1PFsy%rio zS_EKAQn+gAz{mQxyB9f;rS65w-YrOazd7x4G5yLX5F+`Ea zob(0gCl^00Te12x;ia-zY9f*)UnAq(ABnZU!?h6TlI8*t&eyd}PL{c{@r=o}YCeyx zkF9Wh2e?~?!AMNsdVBGHnX>KXWm%yK$Ic|qy)sU~8&sZ|ou2as+XI<6CS3&<9GYVA zz1U(QYwr9cTTG&$!S3VPkVC~0K@TLPW!JU(u@56j4t}?{hjNQjWwXDv3pOg2Ah&>z-ATB;cqsOxoF zlSZ?eOEF)%dpHOUpVv?_b=llO;dhz5O!1SDn$-#BIw7-?loPR#97{lk%gLn3@@wzx z!%;y8C*PrKoo*CV7j$kw(jlqQ%E2)D>S0Z7qi2|VtT6?|qZ9ReCxTCz&qc#d2AD!J zHJsd3f`1sE_Wig_BPU{|RWC{57}rw1I#j}Gs98-RZ0}R`c6!9uw-3MJPx+k=KimcF zaYkK-pyAQjfzxppR!9ph7g`Rg-UfYqm7M`c*Q|1BAx2o7?-tiZ$3Wo(|>K@ z6_g!tQou3pE%#e%aLT^?aVY7*95;4sUQpBHh3=;v38C^=mHzmJp|f=OFDR%vum4s$ zGQJS$mIqGQaV+;vNrq}=fZ3ej(&qZ->9rpZTPqTCWWNkWAI=gLS`$~4UfU20!T4c%yVhMzMzTXH2bK#T-VI*Ouekvq-EJpdt*{pp(X$g;N z?0MCK?9JJiwJVpcX75Fd0h09BXVngApfN={z@AiWRd*fD6<;d~iSJbQt(rCWS^$^d z;L}F-5imXzb#Cb9Xe^+=#}^Nw&w310`{0P*rZGEl3wgVU523qW^_tnz-jTg&iTf>; z$B+Em${U!@URFib^mnJdTAxQh?Uic=sn03Z6%C41uXno$l!tz$NNip!G_IX3viL0W*} z7&`l0#tSFy#D7mzgGD(sp&|xoo6YMw);Bh=erVQXZ15($Mg&8)f46lJ{kCxL3w%!k zV`>t=AokSH%XZU1i;DEjW#-^r+4KSTXe6-)BDcb{nCXGb;HdB%L zQkar8iCXHtX-9lQgHlU|cPHevw762AAKNJqZT?r(_ubEXEW5v}kXh1y_?i+ZFj;e;sd@?DVnw1yRQ&PSRrp5?yt&EajMIAy0h! zW&V5*AM#`;9O(grMD~3+ixw~A9zo8l4cMFnrSN{5Q}iHMVVV?umc{3vLWHD%-g__X z9Y%KZyBmj;l%^z#dP4t*b(ocPX5qVDnP z$sq7C$XEa~cTA*lC%tB~)hilxYBAOvbu+GE!U|cMe_oTlRJzY)G5K@|*a@0@i zko@6A=S1Hdd=w<+Nc?j*{6d9?f-PtWK?4m@E2qeXK>XOkm3-pCv4a!sWe$)r1^CR6 z>na^_HVatQRliw#HGoQABFuH%9z)Bkxc*U^#SXyVC^Cp%*szrnI*j0<6wicZe19ig zK`Ds`a zS3xJ^9;GmT<8t=~eP3)3{2AaeC#T3gjeUf@bB+KV^?8pPzDj=Os?$}$zhXPZMtSCVRmVw*?X`ja3DWU`6<^Yek<&!8-!S~KiCAP7 zJ9^gT2iW}H##}vx7ZV!(uG!!0?V6yyg0i?{yo^#B5jBcTnMzN>{Sb#R9+^dw$KGGt z{K-V1)!>6()CH&k>{#NOP+2)vjIB&k4?8nOc4gjT^)U_+(wyr5|0eeSzn(F z^P{S*{UM;BFdB0DZ>_ixWxXSFdAy{djvkb1q(^dr@01B+B{zgxa*x^R>I=}by~ICj znO;-h)4dhGdo29x>AtVeQo0q_sBu}>5VE}w>+T3Gq?`Yn5#!i3IN1NzZOzR?RcZ0> zc=$2;xBghUo^A+`cpeYTQm&$R(&3hj9?Qc7+ocA}ok~rqPSU*KKV!1FvKRG*YZzJS zO|gP1Wij!S2#8*&rF9dx?vJb(-d<6@|M9W6;i}^H1|HA1)jZ9A2GSd_A+s`9@dmRw zpu@*k`2^=z{K=&K;3{;~m=o>bkxjB97zRsA@J`rN|DbCHg-W%s#hufxq^he0&(9R9z*(zIYm3rpB8BiZW2=Pi;u@srAfDr30B&S{rL@MN@cjcZt zvHwzUX$=Qd;{wtqrnNFIZO(#@SX-AD;46S1FrM2678{r#RLt1}yB7Yf@DvE$H6R;P!60Q$emsYPH5|bq3nwkIcdO0AgYnC)du^OAz zDfYG%-J2~W+UD3|eI`C(zH~v@6#7EX_6Sc5zRRs6N_4n4Xlva$+hbt$_vaP50dxmS ztM3(Lff=5NGj zB~EM^1YPf#3p-<92ULp*Nzj8u@MkTLaZlgOSUIErbgaCQX@*V=RJkVQf6tg&k`(H+pT@tAl+}HqM_(kr7bTHfGOwJTY)y^|^H=z;HDG;yhbl_% z!EN^_iTy!K|AMyk#y|nysH(A>CT(E?aFrH@(Hz_(r3Jtwg-9~3x$=Jjq}&OgsK4|) zQxfrPy6lB;YRzRyqTA}BNp4EEkV?8mMNA2lO=%R})M7)aR`UNm1RvYmz?%>!|Jt7= zFmMu*6810a+yXxTQf@E(jz-e_SsNBc+pVq8Xm5plj|Ij4?((G}VSazN#gB>eDv!ZU zTO*wR`V1%V#|GC2T<6<`x7XVec?+WK z@X-pheqrwArPHpe+S9?LMj9$}OUx_G8CxNm^v~V8{{*_`^EoQW*10%y6R=~_qh^t& ze0{MOrZfDn_mfwnp`vRU$}9)xePj_7`<%bQetFh5K zCk=cGh=N!bpoe=DfTB_B3mpkeI1?xU*R&?GmpPHnvC2l!!g?h?8` zlRP@IJgqF6{ySQz-=M(W^Rb6#feeGo*2b{G=Q(P%(b4B3+;ae``zJdmxm}tU?lc{Z zQEw%FL6#&9^!Jr-4EUG1NF=fEd>9lpu)8#qm)tP}20F^#NzBRF000IAUbm(|coDXh z#!tv`plWXMvd2~tb?%_@GuN<^rG=Vi<*lu$tUVXaiw6PV+9%>uc3q+y@YTU|j{h}CQHh|n$LT;A)Q@6G8LtEm@!6>GVllvcUE5zXS7e~L7 z<`5)}(n!MUs4HgkQ@NyZoTj@%eM?NrnC_L{?Gv5k2l*$R`A^5TVKbmN3_M8)JW zrfVNH`m#{+rN9?uZ=9^h=92gp(4_~|?V;*XaB2!TK|2P_z3TSmCnaa{!*!RUJi?T1 zHQQ4H{fnJOOHb->Ru}oA{q8$jXRez&&8+>@)Q~_(+Y^hk7F}$~6`Ls!X9*0D^8vU4 z`wrN%(`9qvGa2ET{-@?+RrE-R2_qCEAxN`ZGW1Xg#9YDK+q0h}_p1eSd*kl1#qo0W}N&VE07}Uq#Ybwlz-)#mqr}Mu{ zZ_Z_Nvj(Ng(m#HDr1yBEuwcjqYhYmS9o5#Yui>w37(k+x11^Akhk-2;``hJ08Au(% zwM)8+19=!8d2OWYSQj6lseds!Xjv~WN~^5im?Cs4+~N;@+QW?w2iHP%x2W;t)Qd5x z;l?(rlfj3!oA6r~RvJ5244>||hs_+Qe7rSDF73Z@$gABFN6GJBr8>u}*ph}>F38{w zHbwQ?4u9$eNk*tR$;lRw7O$1P9_y$UDu1>2EIr!Pc2kpOb2KI5R>5}F_eAK1Y$$nS z#7E!g*h;tL?HSM2@y1=%MM^rNQDqvw^B!~~CCv>A&C)s(Yc%3@l(Wul&S0ei%TYZ8 zn0)h@x9|6>vx`E<7a)|`=j6D(!e^;p@x22}`0Vobmz1QSADIs<>I+<&ZB^&6)N!o> zX;7F!&UbtxL)c_h-(C?TOnFl9SylUWzK0baj&IMKcb~QU*OBNpy%r3i35bgWJfLBe zsE=-4P>rIrVsZgvY(pc#H((?8H|%KOr4l8Ghy@}s(-Aot!*)`X<0Go==NhW_W{KzY zfd37j!FfWT*(};#sqg%CF32*M`>yU+)^J*%8Fj16wBts+H8z7pzTUg(e-ue3tn;XI z*wfja(mMc)`o*O7?NwxBtp9b;AG5^ginv2f5X;)*k_%X*fUnW}9beX}(#yqx;OFBE zqFp-Gg&ZrEzN$ADfhSpUm7EpMRjcLxe!xo+LQg$aBs%$)ezNo-XL7px4OMCEw$^8H zVV2AO@o|C>vGK2e%CTxBJQM0T0$6iS(s{t23EVKif;TOA^FaHFh3g=C+;)^2Uo=U) z$P`eJ34Z_2+TP^w)15>gRLU;$jU{WX5hF?3918vAd6)l$Ql=i)?oPuHX`|mOZygqU zS9mJCujr@)c5Qv>!KTx!SPZV?tY4jN)wWB6KIoBW(755#Tui8S-p+*Ei~(D72c6Z> z7JCrL#F_L!HU{(WYR(?DT>&<)?Rt9d+}7#Rr(^sKzj6x zkPJB!M(O#Y5LW}0bsty2r1^!J9D|wFkLeE^a3-QfJ+7M_dqSxINU4C{HijvO;!zk% z0T$~Zn10I{JJcKA zD*7|OHaRT1LC;g&zqdO7=4(5->LYmWPAOl4#L4;u55nmUfFB4tD7Gk(+K%NR*L+U3 z6*(o2bs(V!z5tpL_(NGgvMX(KY3c#A0k-Y|U5$Ir_4qda`P!VevG5`Qs&W}`AHVsY zNx>lZJSE5jNRw)jqZO|sPq)R6{+h75>bw5!VS!z-Fb)TF5I#s=j#gW7v$uKPPWi`L zwpMCB+l_POzh3CG3nDx<8cKJ5%;Fe{FT5MNscA|C6R;<0QHpr}atZ|0%N`zjgN*9` zCp%4L_oHO3{m@j%xh(yJyRNW3I@s_&QAw32b2a@^kfU1HL`{BpqWy$@9 z6dNX!TX9#_4P2|rWXhMaxrzW8M2fck1m)ICE$nbT?Ni)HqI*VVND=!#!%oR>!DN*XOP8uyn0!QB!@rvYDf&b?#B)4gv%RO!+~q+e?i#PdUwx39 zE4b=>AF3)ra(1P*Og)0Y+Ru@pDY^tjFkfMF*O!>&K)z&b>Zs~9la5b`RAkmUw1LM7 zygfV4n{m5=tk)Cz9@CbczAuoq^j^jL8?tgWLp&!Hka1tG?}t+K>HEWsvP_V3=4l+EAFVXY>ddJM() zw+&o#f*<7ax}4rWgY?zAVTJ6M|A?W}OjrzX&Yp49ifDx&gQr@}W81*%Gk?~Q+RDU5eNGW)moJb)e?+?28$7(Ch9 zZr=;%4_~U>F1^ojA@{e+UOdYN~ITm{}pK`gg4%a5d z=tg?VyeH8-CV!Nv@OyTvtBR@)b`tig5A`i2&Z02@+_j9ErQ3C(nbLp#tWrk+)azF( z;eMFVko{VUqQJj83(pfEI!^_-jT}1FgGrBT4hw}30$e{xhYa`5@f7Xa7;UcA2;>|b zCv%z5m)1$02YVJE`~Su%va=U*it2{?JPx@wlCTb(Y_*|w2;7^<$P|+EXKmcHznVKK zz_%*CWA3ZtG}Z~qfu2v_JU0KsVogPDDK+hTN_p5EzNS-Y;&dyx_Nl1*DMis@Pc;gKS+tdAGaRs~ocf`6x1SNLbQ zW6C(zJdUoz9S$0NKnw87 zh#3x|lTyfbmS%npCJ(cN%-@eEkrHQAB0#x|LfIu!eRr2byteD0yQ0xy=-?!RHj~aR zXR%=?-pr8kGj|hokYb`0C%aX( zNXhUFWhm@*tJvPr>yaVaS{UfKFkd#L3j55lIS~ISKmOktHKDtYG=an*bFs`&fvc>|YfHPh1vcP+We=RoIA{?PGs@pSK+Qj`eWW z%i7?;lc##(4tWqy3)g=>4u(fOp53)6!s;;p^L3XK%VX4;eo5bb5P2V#0l`~wP2KDN z*Fj0;6@7l8)BE7n&L?V1H-30yJ}^yt=+O$#>SHU*_Q_(`&S@q_;G|>ZbzeVv;lpf1 zVw;FD4uZ6J!bj1(1>{b&u=JrUE4%vN_T!em+vh*sz}NV&MBNiv5WOpa4`vsbpg9Um zUu2;Pcxq-(R+eZiO)RVxPM{`rj6{9~63G|NA(gN%xmRBKvY+Ndq_h#vlriiT6k$yQ?Kt+O_@xC_)k=AIXl~`w1{aJ3^xeQ1i0+NlEScH=>pdZI4>2zi zcqD1R(uAu(_EMg!(JXuu0K+f1=ICe*@(PvJiUJtZnMgt~={2Y2$IQH#fKd@V{70W} zfU?gueCXT!n(3{nErrDx7ZvD~$4zc+t=Dj*L{G^_C)2&HJ0BmWoorem-GgHTBz=aG zhFT9Y9%^2B{hYDQWMn5IC`YQgNT+ORTdC;q!TD8y&Xiq~MCuyXWMaGOwjbBcxVnfd z@ffgbEv|JuTQ1i@u)j~fZNP)kVc;1Q@}5jpesb~I*sF_O&Pnnduw5%XI5F1+7}bG@ zpo6ts9fG^Cu$=UF2KGZU--1akIykcl2Z+!{b9d(Xj_LMkvl{LTFk7Ad_*>e?sb!mk;ot(vq2z=LqkFTVaPWE5P_jX3 zs#>3%AYO8eXb5$wp+cOrqm0%nj`xcLUWazyR)i;~JUe<{M-d)hQL2!=S-yxR&&(3L zG{Jx8+W7u@Bkc(Na%-#rZ`zUgaYLnd6}?4APDj*sOm z&6ob@Qk+^#M}qP)j3^zfK4o{VwE3qaN)9QjzyPjsFN>zl)(_cWjBb$1>Hcu@8Ys-& ziREP}yhJxTaLvO?PwRylB29QO+@REJdT)V?SetUQAK=Q9q=w@`JnhX>xch*9=x5#O zd?RfnQ(ir`XB~jCKGdc^B5x*&xPrwAXgOPaZAL;%L%oCCB~xj)4tGa8?fuuL&=iGY2z<+5UKssB!w$ z49Jvv0yU$xete{4R8izM5szQ?&d%i7X-;*Syien*u><_5-@gFX>Fk^&)tgsFeioJ= zY0_jV`T|)Ud$vu3pzTP+sa1qY+JHQLV&gZPBL+}o0trkI^b0nUYDPEd*;YHX-c~Gb zbQg%EgU_Yy5|o5Jg0~-0S(JxqxsbRS4U0@2kML*1{ARCx>sx4dW=bpWlMA=~5k-SN z@e*Jy1gthbcZa?}?ftE7qxEh~jvam7X*H=Md09n>oCN^?F%LBeJ)TMICOrJyfD;ty zSrc=y>~53niPVh&Q(5^@U?HkLUR%}{)6EEi!%@mkoj&-+kRYn%BZI~;mAc8s^R+-9 zCnHT;c+y`as@l};(Kw&@lU-yH4Gabf!yj57&mlwEY)qcd@5xk7Bb(`Jo(Qe0rJo7hBk+5|ABp55f6L`lZh9wO`lI6M67l80Wq zR`x++u&kqPWCE652;h^kxD%;c${!Dph1@+*?N&CaJo#Z-S5v;%$6$3rSrp$QKR7K_ zUSiJ}ab;!8kplOrjtrZ#ntJ=t262CP@=Ff>;5M9`#5PrqAyjyOO4Mb=lt5SIM@q#m zq=djb^DtalP9XYcvxEz+z z;Qusr(+3A=h|UxiswqimPI_m0?bqLK=WAD+1U2Nsb8`ElG~Xa@MkhZc$CX@df8$gq z|ET^`odI%s@4)}^Mriy^Ez4c$r{1UUgrf#BU`!Pp_s;ER5c-uk{>NL-GFsQhEj}Uh zqE|MnEm#w6@$X_U>zk@_ z$He18BdNZRt@AslWotWXN`ra!FaCf(SqHARw#T*6{cht2J?|g?1^2$ywV1z`|30z! zhd2ZH-*hDz8tZ=!JxymUtexQ0;ZC7}McH-8nSp8hrqo}mYhd}lyU*({B=T|qJ%4`8 zGA@^%1LtFy?F)8wR+BJ(?NR5iPJX?(P@VmyrcMI82yp+mQ)t4R)gv;AnMPmpoIAw( zRfdrd#N9z*Bu#K|_?Qai=B8-gWV$OpT)8CD`}Q^3%7sCJyo+r8rDE%=ZjhAD`n9IO zb!oqM+s8JQcm7(NK1suxMiq$;38B!b_V1G(VkT-8%jxvz?7Y;9FL2aVy-^PyfNoHY z5zszta8*4gEbqeZQ)X_9@_4cTT7977U9v(Z8q3qfhiX0eO>W_Z6FzOpF7BsAqeiDj zSaw)X-$A~ghN}F5sr%@2UA?Z6GVU9<9$WwhxZdegzb7A}@3a=41{-z>RLDoQI` zyWpp#iJN=heJvoJTPEt(T{4(-!~>n{GW!fmkqV}K7O;2Ud%!G?9w>)6d`1n9<<>K%Nc8(lQN?mLp15qicg|A4nX+KQh_|mDJga` zIITq!U7SIIS?Wr!(;~vRZ|8#m^53%q7M=2{#}-1xCF>wG222$vicRMp@vU6Y;mOx0C=P zrGEcWKZz+0CO25`F4^d&p(JC4%+`8Sm7xaFfdW7NJUI#wrI0)CTBXz|eCa8Xzt4w} z9H~jzx^O1Anrj(7$?t!|&p*T6b zR~G_e<@GG-*nZlu=$$JxD8}^|-A2h_73u)4yC3#H)*ikhJ9kfn54THl#GR&8v=Flt zu(WaelltPgmBEwQ;kW1Ke69h|RLRVQ8|8_<6-te}9>8)vAlxe32HTXZx@p=<-fO&$#ECCi zvX8d*pKv+eH-MFAfeUa}Zen>hXi9dz44s;jLsWbrS}!d(OAc$RqgMWq%2lG0E%}Vj z9x4!FG!>dUnT=4_o9$-{3w-TG)p3+E_V}L~tG|FXJ@Mi_z8}r8m`i8vC~&W0fYnrO z6?X8%*_E!)C*#B7km|IoCrAEs8nWldbACq&yOghOP-dD@AB8|_OWYiVn#3~MsY^I)dA!5bhej){DM+T0%sAX@&%Ar+uIq;Gy5t=rN~#NM7kHT zP!X0larW5q@@NL#de*E0{;BLQrQ3Pae3yelaFev!VC z^AkY5M;8ej4fwRa8j*SH=ZGWkwG~a8v4VVtA$mGbzyi4KDDME?vF#`>iVDUva;*Jl z2SjEkM|VPWBptW{fqzxQ8D4fP9Ydf40e5pMWUx?{3r>z6+?jE0^}EHQfd}US$3Cb1L|GQ&kUj&N zvwFK^@NiA1rs|)(pBvN=%p!G#s;fLx$-c@)06 zq@tR~<2;7_RX_e1-GTcSSEU^nqelL9+ng(hcFJT$&4V`aoSU&zN8 z)Zh@|eZuG(N6dB%2~94EXnOZ%Ywh&yi{ovu3Bo8t>Rk-i51aJ<+1oR1(@t$-UAqgq zM@Yz)t-Ex&P=vE#zJ32z)k0i#`5##0G9eu&xCjrFzkQ_kTCyim)|w?tdE7rW%gD znBkeA?7HmUbjFtcAJ31oQF~>#+WIOm{_)mT$S852x+@^Tl#BgNCls&)YKdv8{-ZnK z(LkJ@#97ns+P?f3QGOv4TA!lejS#rfO2B2+9)x_8>~WIpaRKY$*tci z&kIV1^4=)hTv8iK>a+U)Vryl>T118^D4~D*Km|7$W&D)k-=pcrvP%t_XT>;Xm z-$nW~4oIgim3j-XUzz8;CBP5H6PS+o#Nb(DvYxgrZ-SHFVvTiQ# z_YZ)@P1u0@x{EDQBk>HgxF0JS3}?+YhGQm99Qhj^D5<=H5AlxGo;BW{OQ7#c7J{@x zCw6YB&B9b8Q#PtP;`M;9>Xz|1LhmPd;?u8OV53=$`=0Wy8MYYBWjF>m+TB-i62hw_ zBC_vzWV+R@8D7@~q_v-xIfJ+@74VDv- z%9xjNFKIB_Xb_ZDAYVUnrYNGDunjq0fN!J-zGeneze?%HgqTeU>a?-afm5A(Nx< zg0QtR5Y`Y8d50a1)$!~-I_>@+mjq1i$b4w@c5vJrJm=c0Z+&(u+59BOsVON1r-dzB z@zvMH26fJwt%(4#NBm^n9|BSnzm?<#;c5j)cV9k-1)c|9VB#{dss9t2X)j7?n)iuG zFz~1;=HWxM<7jBCI{W5NttinmU#gPVu-t2Uh_pj2y^?aS(bsEH^BmLme|y~$?GO9V zCSnDxt~c9tEF+naJ&J!Gw$AQn52>!YoPv3L%mKaSZ@fyA$+TI0psv) zlk?h>p&8V_7Z1d^-o1P3hF>@N#hjwc9ZhLm+T_=W!3kDMsrqOVIQUukzN0~l#?jK5s9^>xX9I+E*mW=PJ>idT7JTUkF!gVh?e$+%T+hv@+x zx%d?nr-u(%VRGAkIqU^STt+=ZuGyH+g?1WB=DaihNy+jX%$FG3KSnUqj);@s5lvJn8P#!G0)91ES{NJQS-a_qNF!^m zNR9Wiu9Bbc=A@5fJ8LG+8!G>OYL4<2RuJCouM+Dw=p->u!_U&br<~>6z^coTscB|x zp54O^4RW_r!UAQ{?#$I7Kwv{nz4U^fH1j{N3v*d!VR@}6@B0zoKSLI7dKjIAd$7f0 zciq*gbMn{2s@^i4%WpAFU#J}_WLmhk=uyg55?l7-;WdKX>|O00$N%_TK$I%k>~rLM zp5NDbS^&=LGdQp7KxG>Kz;df6fl@kthDf`t_O%WS=x+Z+w7i({U`bI0eSLHcWD|}^ zmx`g;pBOE7HueQ*^YX-8P4YKm66Rj3YkA?Q}tY07gpKdzaacFl68;&5BQCg^-c_SmM;>*#q)|egX@i#)DcvH`&v|~hv>j+M)82hwUnf1S=>3X~@vT&GptTXhNP#Zq7c7gj#s>3lz!&2uc@3S1k|Hvt3cqXH zhlOpdci8dW`n&SKPfQi5Pljv#%-xR5q5Ejkg#Kj}a^QwUPOx;R)*5U+A8IJN71ZsZ zdFFPYk3#M30rKUrt<#Pi{b08_s^jQ*?0l7Hs^TRmBD@_uE(TC~q2KPP!j<>sNdyOo z&Lk8WW_e4`@4mxaNBkjg#>aQjHl;5BhR%q$(^;ju;$J1|{JD;WY)9PU%}*3B?U02N zJe*o~SAcm_FT?_<7FZbgYuSzIIhewP_-^iL`>nL1LAP<4-Ac4XkI~{H>EEOO-D@{M zDlTH5JW(KT_YTo2x+vL9r8!d5&bT+S#!)Qx<9_2413Xsb(8 zhFD8L5nYNewkZ<>82yi)qJQqK|DNwL&DP4#%N?XPBG^^yFDo{Fb1#=?R?NZ^(pzRd zW~*#5?NVjwxjc>{TZg%D4)u#@J=6pE*WQG)R`>HacMC8KHNJYESk_6|c_Oj14GhrA zy&#Q;=3V{ZE0y37f*DrdYN@oX#=S2(TMN z1mr&-cMwUjNB4XeA`41CkL1pGI-I4VR9o^SGUYp18KPKELDK=VvOAZK`bogCP0WtX zkTqP!Xxjqc<8gYag8Py6k8ihIMm&GW@?SAFfZ?niz{%aef8+ew52VB|4SHse5~F2R zaK1pEfHW*bwghc@_9f3_kzi`p4xKS=zUbmka^+Oee*%TpkfRC|6?#9X^Hu&-+bb$I zzBLJ#D?@_{n%GrrmK6)XnI|fS{fa;`>U;BjESU+6cLc_V@B}lip6pSnetrtd=olWi z|42rsx%Vp@)ZB-r$YWGxyLY(vPhf98vHg0ueMuBnd681WrFQ?%Xr`nN{Tlv_5ASQFVC2DxYM?bLk|Oj5~e9no@BA zKFg1!4_WpZmY4`7L9d@KdIx}>MYS`~!%6wlAOA-UX0;yjoE)z;Y&*W7g9rUoqs&g({j22n!5sqj00w_2v>^Q92I+*eKvV=|V62>01 z10kqvZggwee2WA*xm(^lUa2(UBHzOy@XNV;09xIrw?C5Gvl;h_by|32Qrf4!~fbp&T3CvU`_t|953LgBsV}6t27t2?do_ zQgCLL3X(v!YCu=zG0b3xnWY`Y&-J~9(g+rp4^GTuP8%hB^`PrC>?ERJZ#wCVUx z=fC|&U4H(u4%^loY%D8cz;#(aLoHcWls(C$&DZF<;k=%Fd$#J?s;ZJ3OvbabfF~?7uw+q$ICane8MyO>;?{=Dz@TqCBU7!&w=e{fl2*-d_VqiZhHRbJ0|@~ z_4~2FO)QU;v&TK~FQ=Ctk)`2+^skM=BBb2_d+IQH4Uwk?8#S+~T;BS8Kk7e$H|DiY zwjm!^EWJK)1sfIE(-y=&ep&=1gv~Dvv(c)YXbkTIT8*BmGoBuva6kKaxFOBuzr_sj zp8yWSg{ap2=s()dpW@KZL2MefJ|8Nb(BFvtw2vD&B_+%<8F67xz^~+)<$eFEwg6Qy zuP(=B&QgoqWQdz~nAQ+RC+o3lB<&in(AJ1Z^kEXQPug+WfLRUcO#|mA6ua%RSF#MK1 zAimI7Gz)=Md(PP>KXqI!4Oo=v9Cx#*V7{2T9Cp4wOmIHx8^SF^^@5$$<|mN23Cb{O z;cscMOTz$_&H$4w7(IUVbQ!7U3f;v$1P=!(Gf6JD?X;6Xjb#4MoY~w#199Q+=MEx( zJOeBA!Gs+5u4OvA=iM(W)PFlg>ZU@c3Ae0(LT4n#Uo9qrTA6yDM>>WpjziC%&>l>a zbM1iV5WvR;pn#S=OKY{sQl_rx=|-;vC`#SN2=cjh2_{8x zYc5!V%@^M67=>ID{_sXZC;kcw>EA#QQ+b?sOHWxY%A-8Yp=X*ou+W%Hx&RP=|yu`)y73KE+0TCeR!3UHG)g zG-&v{V*fi`Oi_TyJOol^T9Gw(PQCfe;e&Zg zjdmi3_zhp`>3@wadj5@1KL|ci#`;+gJ$fDTo+Ljzcs3U>S7>999UeOl;{TMv>@I@- zD~a_XS}UNn+O6ku>E91gJJog?Zmv$h&l-i!lS5TaLmJmTxaVEMhAx3MY5=v8Gpjl< zHbb?wzfI{P(bRbzI5~|A^XnX&P#TB_A3<-RcNv}WkT@;2l9g6Rt88yt#enSn*v9@h zF&>fZ;}5O*%oqv8VDzt|c4$m$XUBA}uDgtoq3*-zW}o$sAsyeMhFcS)3UAa(4dJ2q zEdst}B@i0rECiIfRso%g7SHYF;g)o63YFtAsvmBoQ)2#D z&tfY*FAT}Hl9}DrwoDs=uRYQf7JYao# zKb4V2Rn;p_-YS0M zl1Ehb(f)loSZM<{eA2q*cR{ixlyJsj2Z7kWDz$o>CmuKm(h0J(d9OG;qD_@7BKnBY^0nZ&UTAre`1;T;w5j` z>VI#8o(?bTx{kLHfS|ZD2Q2Lx~5`*oPN$XKoOQoz{G39cIE2fZ`BlE_KZu9 z8v6XxznHM)FG(Rc&LkeQZwjcf7Bw(i6v;CLVfhPyH{$(Tj(fO?f1ah^1>KOF3+}NA z3;tUf=;Q0ThmoP5A{IaAKrqFz)g>no$uSKL_OoR%UxoE&xAxm;%7%9GXAVAhV*1$n z+<2of3KT;Z>=>tAG5Q-eo*WVw3Vf;0Z{@1W0D6jJ`$G2RYu z`t*`B<>ogFXmRHWoM7IJe1W{u@}q09Ge=4@2=$|FYf7Dj$=z?h@?Ltz7_Xrg z69SKX)S|%k+U<;0^DM@B%|dw34A=wye72XMMS{m#Sj2F~#(~3kr;8URX+nWmGgRTs zOOlEZhjREUmCEX;9!OAIehH8Lsn&ewLmx3y_JYSf;Y$+VEELB5E-R(>e6^tjOH_GD zRo`R5^z|WA#K4^h`S&p){@?^VDDgpIS*LA&=7IR_g@Bu34OjUt5i)gu!G>Mk_?$t5 z&vNyGX0J1#DE!V3Z0s4L#*o1zi|D}UB`1+pF+dX=jwmNm5cb&O+hxT8WY3)4-#_o7 zz=SigV2b6I5( zc85-du>2V%pdkCcRL*-nxb3UWQ|2qt>MuBH$pN zeKXzkpW}%hrlS#|6?@XBDPgIOKG;BAA=@Hod#ISA9?~S|m69o?zTMEi2S#Ol-_Ta04sHCr;dU?P9cv_@Dvo(~D-ygGmHMma z%FCT5nSr5KO=l;BQQXW!-{%-f4U!TI$^TYW}lK_nO)tk+E)Krql%w@f6dKd4*A7DLo?^ zjFB-RtRY|u$<>NPp0EcqJ@U*sm*k8WAMWT5bXc z=tU11g>?I)rA1BOndPseZb65mV<4KWBKt9YeM&=MSVZ)jEfr;?@D^!BF-e$5 z32~SQ=!t;9cwm%RcwRNH&y z6jCS`0C3TiT~BeMn$(lKhNnvxrZi?`2*~#p$|UzejLjI=mlXTd*t6fJm7wS*+U^u zK!P~L)+hcdo=M2H$3cZcJz~6qWqH1E^pjmbQUL}2v4bHpk}!E^;M6QsHxR9_D8tG z9Y2n@@qG!Pm@Fm@Cl)U$QulJ`-I+pBX7F3U?{*K)bk?f*HMqz%rclxJ233Bg9M887O2(VZhCnMp{Vu@Zf7qvxR0 zR^#dBj@c>GnpNhF_w~%sf+Kkc@V#>dA_IlMcVX+uf&R>iX$_gg=!-q4B(>?_yN~qJ zQk99*ic&zz@(T}$jEfH()ju-q!SCN`)K)MHkwr>$S}n*QErcqWs@RMeURO%RgTCCz zi?832-L{lr_>;H8=!HSmVmKmdlOAxR8|>m}V<%47fIDe0TvMcBt^4*|HkTO?5_*A4 z{;10WMxSAWGkM7WZ4CLca`VfzQt;=_r57tqNU=4WQHE2q_VTYQb;;~NM^MyJ#=RFW zEKJ=rr9oCwz!F?-`X4mY`#WbJ4ZkiL+MXBeSB59-H@UGOhsCMNoCcMUU1=9qJVk#6wLLr~cWp&fX9Op%sU zZ}lEc?joUwCxns$gvsKEv#<>%oQ|W#BLy|u^V)Q%_68MO+skdbjZg8 z`!yrS*Qb;Fe8rdQe?_%+JslkSZh7a1CNSM&IZz?iFpI>^b%YX?TLOL+gE^%oa{S{; z_u4bcWa!GBxlzR*GO{3bpbvnt6N~ir4x&#(c!i?HNs0~{N$HE`S8{y^1ouw8Qw}Xr z@nc9=QH&DmrMyqK8xW9R`-BGRgmAM z#R6aiAzagB#!}e9#yEu6O!sQugGt}xZO!Au&g}HlT9Z+5LgJ(lnBnMWz}G->)rZ62 zUD&Ar9o*?y%+NJl9dV)qlLLScei;F-pMp249td9|fIc0Bj`@A+p$>?o`s{_kS(%vu z2C&KAVxPSwQmM&45x#HFO9X&4N$v5;sLE&k$n>dA&QKR>1bM$qt??GB-;x{r^E*o= zL)%njqriEp%oiVCwwK_d41f%w8K~9_IFUYp6W;;)T}*-eNQ?gTn+)yb{>Qx$smapg zH**0{b`kY51Us=rBkHt&4o)9mOi<9P-$3tQwdlEJn0@j))1~%LXL4)^TQsK(?3s(J z3v|OGIpOLNy%gL=^Rrg9lqQ^VK>*`Eti(#6ZCJGVa|aBra{$r{e zkb2<2p!n2>**Br~bOh_RKpKeccZ+Ss6;06xbXCH-;OQU3o{Ru+A4Bk~xlgn4c^V#h zyflwNU335L0Bh7hJy8_bi(Is4E9M{y*z9$bWQLw73|rmER+ z74jYD;J!)VVN#UJjY|38SJ`<`)|!dUc%|}bQoXRNh=*JO{sC0biovgL?WDj8NpMPH z2}eCe{?R8J0kl9AA?hM5%23l^s5XgJtXQNMy6~1ZRz3ebp4w#cF7-BrVG&jZ zx3lXoc$1%AX+<>g2SkLujKPOAw~IGuozSDlHJ}=*Mt*YI>?otqiy1dNW(gk1798= z(<5SyzsvIz+^cIoc#g8L8`gkpN4ojj&YNCcw#XJ}x}jI~QZfxbnBW-%I&9racljGB z3-kct$~;jTeS*9xUtR9<{0@}mmQCpGuC6Rzl!*n(!Dk#iMzhuQx7RuoDPC~+9@Ngl zI*QTX6KMiU-5nMyzeJ@&kKJ8G4ZCZ9))F|Y)p%oQXyrw&fwE%Cr)w3|o{e>U_J*Ko zGV|fuw{1a{cdrsb=d}uCBFtA~-co==DV6Xe9TVtq`GoxdOsw7aRuN;ie*-S4K&PH{ z)jb2-uVXx(xABXCo|@*w*v7c;JFl7f`*NUn@ka9f2)U@iCsGD5_@uZs-V?u#E4$d) zYu%oq2Sho#1XGl?>qAy*d$69@86&(=4+WR-Z$R%i!6Pkc@tfwiu=|;<_s))5P?Zdk z0N;7Md$TBVCA_kL>vK11v&3{}tiwcu`F3Se&cS6(P;P75zvBlOz3kr7@YwULKRMar zafY4XeYxes_4RYIZexwJ!(vj%vr^!7dr7*J4^x7tT4y7ZGZWtlgk_Z&poCQR!;Lg; zXm8kGLA{lb)gd=&v&^L1gtELyaeo8hw@XMm?NVqPxhsy*+gN+1hGy?LS?-2&zNOfg z0H+5v#G>~(`2nbc;`D@}+6r zx9kn~z(*N>fU_Z3;we?bv3o~rFZoIR;|!>k(5s|Sm~={!K(C)OYFLuaMQE?eKyFYI zzYGOQif0l7JV)F83;(=}i&T|`oFAMgi}&KIM6MimU(R`#&>_%Dzb*}gG1noN;|PQl zmy0&je9P!+F95Z;8p^Cj92YTP)_4gTXzE4M_W1#pUbT~R(+tF`>;bg*+n$lIi5>ov z!<;#JzFTA{JU>Ti+Z;~cBmmOnf+1>vBM%0aw!LREoH5itCaEQdWYyj0W3YdLr1zvF zDN|PrvE|{IDYah$jItg1{Z4L%L0Fh*G#YX=6FT__nC$oeCLA|p)5sz`ffC8Pm;MKt zF}az|^CsLtoBmeEidZAa&%OQXms2WfLWzpZp2HiNOw=Qvia351OAjX3XMqr2eQ#KF^?cB`pzQ3@z;`R%+3jwKe=l$ zAIG{C?>KY?I4Y|sk~IMRZ_=LLt{hg=IWfZm{`ablK~+X*1(|=xMbd@1Z3_Jb{4QfH z&^kKz*b^1vG*kK4UXmYS?z)BRl`-Po^NN}gxa!(>oqJ|drBgZ!&>P#MW~X$rh}iN! z4!MUb4Vu@i@m`_LA(M{qBmrM71ZOdJDe?N z6@MaYjRU=qh1ca5JgA@>x{l(n>giuw`uc^s%uObk-7X&3!6#4UZF2}+B=-hvAdWT` z=Q9zw9S>b10aL*SM?klkV&I9wCVl5uTaviz%Q@=k?u^0%SVz=>7V#vbHTT+R^BKjVcDhdpD=_an|d= z>RlXi8M<^f7`+QmjyUjPH$uG(PQ*GDb|t>2_0Wrdg8b5g8|H^@L++CYD|=hrZGp7; z_2wziA%9VRVR4Bnpd0;rKv~M(hOQ%e@QDNu;VV@bTo`tg51azxF&c0*%ksX<)h9qA zLQDojkygNoegL}$)~_-009@KFe{_tj$%TD$OX2cdxYtHUV%z1vmw=O+^;p!}y`aXI zk8ev>Dtr1X z)*ytvY;&9v(@cL?VV44Cxe|gNKPkx*pFh-ltSJOtyH{gO>vOxgTso_=m6!oTn8oS| zB*e_KLB4yR-Ch`I0(HXL0g@iqC4UZpPDc(uDfi|DJwZA3&e(dqq(xq<*K*)}hdUa(NM6SdK_gGza0(AvU-9`n$%j zw7XdbzUv&d4=GXC3_JCLGucNj5~5ziswY7T2%#s!)HQsmN4-~G>U!;10#%$G)EHD< zm}8!#n+i4bqtK4M#5lXQLv$me;*uUM@2`VwBY`;%I20Ef$nn({n5ZdEZUTSLAab&z zI3@q69sBn_u1lOq!ry`Rxh2LY_1Q-)36`)Ura1?eacsa<(ILP5)8B0dN{DpMp^6#i z6{UR9rd91XPw#c$f(u+mJY#SlEAjp6Q&ljih^R5L?mBf)*RfN_nil5^MN8WBhe(?f z+&j3peDLVtSLb)V5Oj?5d{9I5Zo`!{7>1d%T1ptew~x_MJw=Q4q=K(h%AgPtX`H_G z6sdJm(+U#T%pK1J-eB|e1!9ka1GxY@?F9$IT4E-fSTM}sE#k*BBTfJM=LKj63hUPj zrab--tEV!EXwDATwLejfEpj;(3=5xU**ox|6_0$~S*2z5L74|Xq(WgQ3P%wnWD@U< z5)q;-U{X->h@-@~*!<{{=%~4O__(kdxKN3q?HH$D;6h=!j4D4q!UbX;3Y$n`^vD8_ zH9e`==~};Y4w5=^G`0=fi<|~1DZK%*i=RWAX1ue-%Dry|Io|F1%Fz~|v2$1sc0dJl zEe7e*AiX4%v%u^<7dg|CiB_AS6z`o2(p`|H)d9ySC{0@9SBPb;srN_-B2T1&P)mWeZ)2BeyCk{=iHW@chg4E<@`?j_C*(eckMP6y zQX^GSR<#9|@jH;C8sEN@Y@u}IKHAvzlv&7aBL6KJ-rdIh z&O_=)d|%%j$&m9_ZhG!NeWU`kmPBWEIff|Bu`8? z2k@K5LI#C#y%qwcobT?cI!B7fLLrS175+z#>Jx8o#nX40+V-n}J>mXh2AylOLsG5X z3FPIeIB=NainihP@Zi`f-<l^=Z1mST_|SCu{dO2JB^&C&Q*`itpJrSsZ}u zSapX@=k44&-IU^L^qI^hqCnYbF6bEQ9c#&4>BS2`H|YUW{!WiI*1EDju06fFX?0ZJ z_v9KktU%QB1!zi?CdaM%y)eWZIdB9h0w7Qtzu~FN=}%OX|Z`mq6X#wTS^QOC%eZA0eD|9POvBh?)}a zS5GxWX=&}1)R8fd1fkSRo+RiyJK4$RGPT{g6lzpy-2Is`h^~VS{F1EYtosy8t|!?_ zK`iRVyi=8bkcK6|+=GVD5bV1BU~u^3Or)_Ow2H08l zXh+D4iY=22w^|_7^jR{G^mVhe6myZ7{LBlah*^gmr>1Npzr(oJU8#0=DkA7GR3al!yFbdLD_4YQCMRB8p4G zc-};CMMyZ=j=%Ivh1CrAFWr8CAbRz|f|E$xh-STng1rNrK3^$S{(imU80hZxT$b!h z@NK|fb}93`3A{J2_k61#XHSAOJp8emfmqrMP!gmjwUQdTb5JUOKj_pR`w{$V>aW!= zkm%{WV1A>g=eW+?h=W4_5uEfvTVM0!d1U9P5`rH)E^nWyN*_iIgq^?a`Ry64za1MI z84AKvP-hE&)80r2)?~PmUfK;+z2Ur4@#ffOa2#!xriQM=jT7JUl)Uff-1}9=s4#6R z7#WT~o})U0h8Xz;7>t$8l%Y7>VLW#x^HZGvp5c;jAoRKPk@ zLiL>)fM7&$fu!baW{`GL?q=|0dM{u3O1LlrBx69}n_iUw?xvvUy>O68YT-^)_!7(~ z7-tOL5eAf4ATtXI@jgA8-2qC^p^QUJ^4`p-Jr_2=2u#I32!#g5Jq|A5xJXT`i_oqF z_7957BKRBm=l}c-8|@550#{lh)%TekJm2A8CW{)G58C_VcnoOmo7M2l38C+Bf0QT2 zwb?fdl}y;(7r$Zq*;B$6gj%-z$M9Ehb3AIP*By_tcaJ;2d%^@LE_V1E_-3;^{-`3m zb4|fg>B~OOb+EQh#}J}dCtCr&r7X)De;;;`KyoV|dCT^+USpCbu1Zpj)|Sw3;_>yp z(chb02iOh!1u!r{CT4i!l4zSw)A8O(8w{aN2&mV(pJ$|+uzM8eETL;~gzXJC;gfr_ zma-BVYIVbYK%Yh`HD0YUE%B-F88Gj5^s2o1{$3I=kP8mso{7@-CmKLu{J)}}J09x) z|F=<;83|d5KDM&SDk^)0>=hE(>ugt_G-ZZxD6&`f<_c$a%E&(3WskGZ_`ObjKffN2 z9*_QbcdyrTyqe2pn8GV13iQxfZ$I60Y_wRz$-n`P+pX8#*>8(cQhp-pyp8`XM*y?apd53 zLQTrH?=YD@bMW%|$#G%eXnQq1WT$t>D^al`y*6m^N8aY|sS1V;`#8=FzFF9rl!z$q z^Ok6HU`m@)X=<+&9N|OVN;mzQXLMo0`GrB+7cvc=P9J^+c5dqAuNGj7QmQJFAQ{4* zr=%eED9HUvgg!#?9)xCqgEApe-d%twz=W%|@v{AW)gaFMM%=ZqDJFAgllu(l!kiPb=w}JF+ zeYF(_6{!@hg+^tFZO?QV7=k3ZFX{%NzphahJ$Q5^k@B{al8Hz)HhM9`WivnCww%hWaVQ6FaKLlDEC_U)6CA*vW6JOJezcwVzw1bv%hrQ zbfU9%IYoEVqn`8iLuWn1{XUQn$+_i`O0>QNh%{2YaDzC7L990tT4#nlIj4fM?))=@ zkreUqy&9WKD5N%w`Qkeex1!SjpmNAj5g!`a_~T^adZWpcGiV2VYYgv4)KZ6d!kLHf zh^*@QW_9|>1}!K*oBuY;|Da{yvO$Po5ZmPe$Bb< z${<&HvUor4@zZHJs?)$}Lv!Ja3%?64Mm4e`g&b zT{4u7$SXFr%RX8nZ05pufonZ>AQZ0~s3~O*W=fnndVK(w!d%?qx%_XVLGX`cN6LeD z>ctxTusQ_0;RbIE(<~ksTPt;TrYze*u0H<%#C8mC-21UIR{FVilR@vIC}1IOI0p#R zRfL&Q0w&_)4CaJihi+gae(pCCu~9A~-mu+d(m*_}hb0OVwvdIc&UcL}_L{rpi(z*g z%PMB_6y-4HnjqGZpq38jk2EVj=SK%*l5s^(O5R3buY{#et>olDe!Xi(_sT_O;p}M- zUhQnbK!0oi%9zh*nC9fh0g{EK>$?Jm7HW{34b3bOtd?`Sw+3x{6OIdk6hY$D31LRg^@BP3 zI74wCDj@#y1t1TnQ)}}|_FFVPDmJ(I6>hq9zgW@Z!5}c^jIFbecw#hnr9yWZ4Y^95 zgE8BkqOjmk%JHY{P%RqWofwC*>b!@D?T z7)*TmO4HTT`QOIGCV;r&e4paPuH8ha!tq0k$~G3x$iSoN#mxtLv|Gd|e;!|pU+h!y zU&*~u7?oPE=ZJ{){$n7@kBx&obi{WqG=FHdSOoJ}zU}K=mv2}qYvXVgKs>2c@c12i z^sC0jZcGiqcnSSIsA2Haw|xHEiG?4;!YX-VGn!-w?eA;epZ^tB`DfPCX^!0pg*DiQ z_u1^F@DmGXPx|o2s2Fm;6cnH~xqng3QzL!yEJtXY@y{wBYrD41(0xq3n7SAM(TiAl)7iWHR(;;KrV~3?riY5FtA(`I1M@StTJMmOPtg7((cDr z9I}~s0S=kkpW67hHdj1GQbN@meqd(6hCD`W4QQN?pYq@ZgGMw1S=CW|U5TENVsrN| zj%Vh&~gU$6Lz#CQmT;4foAE zw{`E_cK=u8k&o$c;l#zZ46mkci@27J)&YjlZ5cNDGZDB4P!kA0sL#wJ0g`tjy@`5Fp}VIV4S(FTNcDW&$s{ROT}cj^q2=-7rH2goPYg5h693-?GJzlvjnt<vH*l3layx|jHn zt>q*ci}_WrywQXQMvdGW4{MPg#~0yb0QsWT*MKN58NPi)38n2JeNC?bZUHuN)Uoj) zH%Zhh+_&a^#k2tDwWc(@P2Cjhguky#&tO_WCc$N)xPW~SDe`+{`*jp}TvSNjhlS zA<5~gmKL$&NqJ6huGSg0X7ZM1sg|N}q+fzu1|sB>b?P^YZl`>=h_N;#BkAIae=!(& zApOw0O^Fz}mhq12`UV4m91ye^AxQ(TN6L`lP_(Zz@Dh|0i5 zzXvj#%YI{u4RtQ~{ic1~MG(#4L8pkl6E=J?k;%2};h<0x$R zxoV5iM+Wf?Ai9`2o(Q7w)w1A%VHzof3ocRE_cIlpA@oG^z|6Fk}IOE({Ik| z=)5BBi&a-zcpV)jQ^Ngf@uSt-JvsK`qPX^$+3EHSKhr(bqEN!o;%jD(ThB=IZ(cN4 zDB&&-(L`OykiE31v?JWEa%xM_B%VK3mJZi`9E9tj}Juesp-3&D6;JcuC?q} zYtGcDXs!Amuvo3D`M>Zod$qUGyBOt1ND>Tvt5s z-d!7X=KI?h*7LHBGI0E%lRvjiU2T1+uh!j%zFIXR4e17{wC6yBjis=fu8fn1X8Q7? z*&QP}K5YETiv@@P?|SCn(WtQ9qn;89fT_d z*t;zNqAxryQU(AwGW@oS3s5l~VEm>!VRDuP(ojv3HqzNCU7m}hWc zi$k%5KiJtN^FBTG^RXmTRJ7*t_B%Xd)ydAb;ncZnpE3tNA$LSrRKkVPR-|7(B_Cw=mT*p)G&F!xokos-L2TlU~J?GFambokFDIK5$=Z+~`~%umrnLtMdz6|V6a{qDA{(dC2&p~@t-sN73 zL|xX^Y_2pZ+`W^~jR=u;* zYZOD`ZANcT2YF|2<$Wx}lDlIAe~DiwW!&Gl<8p~qjd1JW?n@=8Fffn!0Z zj-qj%;7o=-&rTZbP|qSw#`lFtepbDD+#IBGo2!o|5Eu1=#YP8h;}B% z4$yc1UvCDWO6O&mu_U9(s@fO^4Zva^c6ICY*q4R9YZ6sQc(9+Y_CZ`^@!W~U!47)q z_+XI`C??b{OdtN}h-O)7Q*1WO2Xn2{NQu zK8WTH3(GI}4iQkchrQBpc{sK$PL>UT_aQ43fX5S)WvGnc7`6?NFm$e8&6nkQLE`_~ zi!(}YBSNKBHt=TsU*2iiZ!a_>aZRY64v*ap!Y})yo~ycxs;Is+zgZF~fhqezBn<}T z!T_gUPq-}5auH4ZAZI0Hez#=A3)@8W>NUiVi131b*vaTGY&%yzS8byzyNr*l;6l?R zYZ!i6txJ&75$>3HYSOHK9d=}|tWT(10Axf+a}4`DL6v{DA2of}@U4}0ZFsvlp zAV1rid_a}aUH&{xTG6{U-TH3xU9B>H^{n}&CGU>Pco!-ip~SyCL$wi+tF;vk*NcQr zODbnquL*pPY8#h>-H#L0h+(0GevH+)4IGTG_@+)Dx;K>U#kyjJC_sl?n@sq&s)ln`@Q=F${(RMKzBZ;buhPt1JynqfK&n@yt+dlf8w@Y528L zZst}%e!s=d9yi4&2Q9h#hXKw(HvV`s+0mf?I83_G%qwzun8Qf;V1Qoi(aCS>z&;Fm z{vjLB-Jn!m_NgE?I0rb>*Mqd{4IcsG!Bq!FmI^G|Dmw6}$NeUnEW+=ZaD&+LuPT)2 zqoFS=KWN$0uecur!vrvqC4t;H!1R2N$-Id#rZ1 z<7?>ivo3a3w_i%P#eCmA^kDT!C0)N#?1p|LLjZCd09iEv_}B#!BcgNz^YRD-oxNSG z5=R^OY?4;X?GqSC&~8UtZDvKXM=fgp$EEaG`8^)n?-*@Dr`xF?G%cQ%C~7!Wmw9;rhl zC~y(6reieQ|1YfUL38aUZ} ztxsf5%=*=;19uTi_UPOvaiCq7)ibe5tjm#J=+^x>j>JCS9>$)$_TAlbj6rS1!8|@M z<^|t>1l@m!BjL&UhgE!{*5>Q#qWj09s5T`jx&3d-J;kFB!+#!1L4x6ul7b|*lu*@2 zv7N>T=3YNR%_On4d+1jmu-D*LH1`uz-u3wc)!%B7dF7YRqnmuE3wHh(@+UMAzp(6w zv46+8A*5mKpx#kOC++4DUNNoQcM#(eCU=RSV(+s^(#cA@s{{|48E9@#QSVg=zL?MLwJeeAUPi@%>T#R@U}q?s0++f_m~QYjszhvPXzD^XRYS zK>Si*Z=wmuK}eK?^vPCuEykhAzfpsD3=FMV4CgU(a;|^68|vmaR|g>IoYm zZY9ihcdP!cNR0lWFMM~w{X7~wVAz(rkG;;TjjW-)fj-`j1=Z?*xYFMSWJLr=QI1vP zQVlg_bu~Xw3Y^6nESdXFp$Wdz2%xe`Y&ee^EHEH9Nze=z-b!$hhw73A^b<+42>`g`&ZV zbzNPMn5Ze3$mF-z_G{SU?hDLwZLIpo#q>Xjh^B(9RSe^<4Ne@eb@7EtAAgZtTRH49 zT062>BL99u32*biDvdhJ0ocx$w6J<-dJsBfgzFtstnUF_c;D6Tc|~facr&naSAPE) zPHhTavN@sw++wgReX=Ta<3AP;1FbAWM4ea?OQ>Ba7{kshZEk{=SD)_VOwU29U@RbQw zm4q6{KUVrT;OelOH0CYm#w}G{`X;RsXYWrsf1&}ozLk_Lepg2#F!(@?xZGxwks?qJMBG z_yrxbPn#QEtoPWytJSBjtdH0V@PoM-^)PZI3FM%5=YUL-Np9v5u)O&7!_x2SH&(^x^CkgU8YwAIuEt;w*c> zq|Z9K7bcG=rr6aG0;SJ0jm)c8X3xd-vF_Zzfv(5GjwAf;vn{3*@_ncDN_p)?P6WKh z-5u1g;F=J$xb&88uN`Wr#(iHl$dAyRYnm+ww1);F`aEqMKo=f9!pD#8ceI3sQ8fYQGBDx2YPd#Q1@ zMGbqqKa2@_bfw*eHDdG@aRo&JRKE4y9; zMY*Pkb2{xbJLMW`ga({#qjn-i->l}blYd9&Q}BtQ><*LsYlHI1vr z2?zbVxMnU+hBShngK!v`K)i?&coW+t;UYP)^}%cX^roT5HGTOh)j^{N^gOjf{#rgS7uM4?uKsw{DBAEUydbRsPWZX7K-;f`bi5E~SqU%(3&r1% zs#RN1&Z8yp@Z6MqRyz0gh#^ksZhR261>)E6uJDdeOYHw<0DD*(OT(Tx;ahswdx1UT z=Id?-;@fiq!iW`^55$p!4`W-;6iEqcthGXz~0uc#Z!h}42CWlA|?%iKd& z9C`L08O4R5JG#`#xtor#*JA(YUU*@r#|m>-^gFNiuqoyqbo>NDy8esnlbbq54wv9* zL?4t9;O9IjKmZ_Y>ms~uY0d9Y3$i++YoaQx=;Bo9JFHgLIJ-5sRVR_`yRz`E=l_M^ zORvbHiU(oDYxQnYJ9>ylsmc{`q7VL(t082_Ce@fNNfoQ`Iis;>1V2Am01nJCiK_cB zIduLrg}LlB*&}^OPTNva=?d=TcysYTc{64ry}LM4|79)x(k zQVUSMPzW>$;<+V<;o$LiS$$@KjuE3tA1#=^YY#0guqG^!{D@Uu;iuU{;csnaLdS+NpM_ZMMdF)I(LuBQ z08%7dH-kKYDCP~1{We!xd^FP)`=8D}MAeWEf&9!AI&An{D8Rr6u_$4v-ZHf9n*=0Gx~`W!dAO(_xqI{IvpYWUiIG`fd{OHEqDC$L zA=BpZpEZY;hNVAoSEDi4Yv1>|?yJuZ0nkUVaZEW}Etege8G_sSQx={t|3Ut;(L0BeYC_r*atU+`RNkzb1{ztSw)1< zM2O9I1AQohy*f_1Zho{vkpVSQPPPPntr1k)`<|JWn8~*}tCToV)yO*VKPJW| zYpkfIL2igO_)U3$94S^woAe!g&(*^PEbJqC)08MVPo- zXjOoh!$|pm9OB`psTCcVul&@$O{c)$`H}swC*URMVMf^*`E!#mp$INCvjBo%9eh)& zJvW(nFv=)Q=1v6HM|obkStgerjNPJFj3ma-fchf84BvL#f2I{j?|4vcW!cr=W>y#0 z*ScRSUJP%UX8sD4gj)=Eh5J@Bh{rH>h33FWs+*2?!iuldjpAE=vhURx8aBd?c|b&j z@4hO|6XsUn7>sYs{hw{P|64KZsz&aYwzAxtvlBO#h33Lu;|8FjIPL|*2wx_FZi4k5 zMzviCg-}jjuK<(d-DGS)wxbSfDp&+$R`?xKbkmaJz($VllT2Vf95xZU0oeI2WU?blG2Fj|E@cJQ) zL(b4x{;rI`;Pv{ULW_^xYb>2Kn>^5ouv+hF-P+U=48W+jhphr}iH+%Tqe0 z0tNlfm84j(4gI6&tYVDN?|h=5NQXxbAS@itz}Q~}&RCa(vZ3i9C{yL;dfiF7j@C~@ z`+HB(>HS=8MN;2f3Bedy7f#IMw>(R=F}WG^FZ3uTo5{=oWN1fj^jj9}x9p`l^&^Z{ z-0cZ!lNiBpLw_*TH;4RS`?g%KD3e5E{W z3`D(dtW{kvP)d=))8)oBzRVNJOK94gcs_QeEd zC^f(7sATYpyD(g5@&-?gtcOyVFL-dFB~jRp{83*Q#r_k20||v|tmbE|4UI$%$D>uz z;r8Ktm9$`D2*T?!n9fHuS9j8fj(M|M~7lqHF#ANwlzJDMfBhO#`}?V75y_# z70>+&lmw6n6?#8BKDja|lsO;y>^(%0n>8g$N0MN$cSa%KX=$MH0)-?R~H*JnKv z*w(c`HqJ8Ub0KT+4KTW|sl{T9*;ZK{yfCC&7%c@+5D9V{`sZeFt!d!QcU!RCaecuwO=l28 zw66W_1_|57?0XEja;LZe5hoS4RAsy--81!V6_6 zm~6RZed+j1>l#nmU+bP=^flN+8XRGd?r|B{Nn%q4v+GY5_EFTT3g|yfVpcV zV1zBQ39%-v*xs|Us{Yw2P(SgtNAm~k;cprQ8{FSx(mZofulR>}*jeUVG5l$!KhdE+-;r^IeF$fR5`gV`A&>rrNvudA z`Kb@PALeDDR~szsqJvy<6581JGV`^W{d zx}>B@v@UOVy>FgH>LYBMa&73lT=V`{Pd;_9m+DF0CO!$e;*zu)++pAnI+F96n;OdBmN-qphx!PlcIcmS>0NDRXPaF(!|@3IswlAnI_3k&z!;Un8Z*iWPUoKk7iW_ zn45m$72orhT!<1d>>K_g1}2g(cDOEJxeQoHErACL;9&;EslbG@{TIm7Nqwl1WKt~S zD98a*@%!l=)R$Md=E1biI|2F&oyMpf&BO;F*7uFWJPpjx^Vgd;|DD%6Gte)Yrr}0W zW8p$nmG58|0@l-CcuWFMxbj6fppQ5;Iz=QtVS@>f2NN%g!%skmTI3$$aA1F3hI)AA zERv)-#>Pp6K@VbY9g#CB)K@vs=$%!dn3Ai?^vI-BypvMnIgm&7KRk-~Jk!kdWrJ!l zQ?La#&d7W(U9&cj)@rFaXMG0Fm?0%R^j$*0R&cGY32`P|gy-6GUZQm&hyv1N{p#T~ zp>nbteHUaq$Hu=nH%O)MzqJqF{A?4?LsiyYzH$XHo9soblKy+ksw{7R@xrdPURh;! zqq-tquDU>R4~3X*$oTx^+D{h7Ew7c1Q-SU5{iz7rlY^gyPQ=IB%EE>~hE47Oe0v{u zGRX!4UmDLf*DOkYV>IvgI|}C_A!b|cx4<7ju_kh>U4myra@U@J2wT3iT}(ty>4A{0 zj=t)lFe{r=>iphs%;g$8Y!q3{L)pxs!E$XQ+$2f#drY}w98)|49jzz;G4hwVI-RqY zUhR0^$jYz&U`xZLox1H{1&cL~z#KYkb2qep7H*UdFxe`>ZA-8QOEy{$&O(FaoX7OT zWldIRCWp8J!*ADf&|xz+gDkb)`b!9%wZ>|FkNsMyp`4gj+D>fTxf&3E7$y8IO?j zP;ntd3w2SY#LQjilj7N=#X*&k5(?O5j#_#L-r(q5^)#@1M=t3X7PcTSY^XMO-QYEj z(~ija+~fd2x1`tiwo}q}GaFl-wN9j+9)%j;EWe(k_Sf<`M^1;`e~P2gFnaI(+Q^Xv z)08iF#d@UjQqPB{?`_WNXE6^&!kSC}ec^%+qviKll|yvJ*yX(GFYfTvG6V1z?LMWQkRq0M+X9FF*h;oIykBl^Ap=0H=V0tTmRftAU%J zB8$n@)txgc{FHwj7-(X2@N=`S9Fy{Vfo4s7<#kO+fY5(fGj3$gkOdz?9qj zQ+9c>#IHy?kJ^q@j+VPr#o@v|^8vg#9vbPE}8-w}1K<2|==DYrehTB)6y zC=i{zrSJ8)J9O=2c59q-z`rlbWOS&T8qESe&ZR;4X@&24_2B4Sfg!J++0}!6xjfAYPcRUB`VpiE|7c(E$p5l?G;Z*To!6 zE0_K~aeFe2Z0@J_JA8VQ%kTN7?7NC#(@$w{L`{%=PJg5wfa4RXU; zqszX4ZexPV$av<%fE1A_;2=ZZMR+BhT8)g5HDpXRDFi+7HwPpnm|2qX#)FUu8Bz_J zw=2=k@g#g$pOZEGoc2ldxM|}*0W;6ULBrAMr;WxZ@2IU^sh8S_e~=q$ivgL%_**;~ z`bFZ$qErxpslL)t0eWW%-^Ldk!#L~kcr_^E>0Xr3(qEr?U-A1{xDT)mj9D6{_|p-8 z;Pztrb%K?;T-sK^k)~Xirh8gBH^$kAP}=#h3G?KY+A9J80mm$y;ruUqsL#t-k)11e zfiM{tSlhU%K`Lu4>iOh!Df3qP2GDgy0RJx0&N)cC-6oj$)KY2Lm)61w+f~IBpZ!4x zj<%$G_m>}>3SLIb*Nl}w5kxKP5oUjbgo@s0;qThn^#KB!4e@)z-G9z6`S;}+B!PUTJRg#&CLgoB`MAol_BV7bi#CgDP}mQE%>188p-!b<_&cGY2I!HJ^(D9o z^k?r&8;}&}50QD+F9}2+UN5U*9}%aYV$-W_vYrL`=$7-DFERl1!2Kf7t3yD2$ulCn z@~7Q@*#`c#o@bStq#w_gOxdUL*P9g>+E?zqz|%@$7%!$^BgI`XmpdkA>dT_y-dn6tHTEKC&TQ zAtC&2_J-q5h2tIYrcQ4l1Fg_FwWsnmp1tL=YD)#D1C;HtMYKUB0xvg?ILtBztrDl) zBtR$dDJDLB9hZkz25KVXpsU~x3NN;AePr-E5ehhBkh285a>}U%?Ni6GWIhl>jhP|! z3PVk#0{Br5B|bZt)&b?@KCt;cd3*f(JUbV71E(ZLp{Unr+GRc`JlcpL*m z5&cN6TREvuHbVls5FR`*@Rg1$$?Bm)__~AQ)hN8*WK%Fy4~;QZ`!q^>xRSggQDvRA zeG5N316F?eYl)J^bmi+CcZ13KvXc-ZhuRRSoL+ lP1DpGTSz#edHI9}dPjY0t@X~MpAh(?c31mOk&^YZ{{ztB+%o_G diff --git a/BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.svg b/BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.svg new file mode 100644 index 000000000..0fae175c4 --- /dev/null +++ b/BTCPayServer/wwwroot/imlegacy/groestlcoin-lightning.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 73e280157d90f54847d1cb86cab8d2cf20c38c1c Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 14:16:23 +0900 Subject: [PATCH 02/18] Show the gRPC cypher suites for gRPC consumption --- BTCPayServer/Controllers/ServerController.cs | 1 + .../ServerViewModels/LndGrpcServicesViewModel.cs | 2 ++ BTCPayServer/Views/Server/LndServices.cshtml | 13 ++++++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/BTCPayServer/Controllers/ServerController.cs b/BTCPayServer/Controllers/ServerController.cs index 524c957d5..f5d61b263 100644 --- a/BTCPayServer/Controllers/ServerController.cs +++ b/BTCPayServer/Controllers/ServerController.cs @@ -520,6 +520,7 @@ namespace BTCPayServer.Controllers model.Host = $"{external.BaseUri.DnsSafeHost}:{external.BaseUri.Port}"; model.SSL = external.BaseUri.Scheme == "https"; model.ConnectionType = "GRPC"; + model.GRPCSSLCipherSuites = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256"; } else if(external.ConnectionType == LightningConnectionType.LndREST) { diff --git a/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs b/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs index 33bffd72b..619463f35 100644 --- a/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs +++ b/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs @@ -13,6 +13,8 @@ namespace BTCPayServer.Models.ServerViewModels public string Macaroon { get; set; } public string RestrictedMacaroon { get; set; } public string CertificateThumbprint { get; set; } + [Display(Name = "GRPC SSL Cipher suite (GRPC_SSL_CIPHER_SUITES)")] + public string GRPCSSLCipherSuites { get; set; } public string QRCode { get; set; } public string QRCodeLink { get; set; } [Display(Name = "REST Uri")] diff --git a/BTCPayServer/Views/Server/LndServices.cshtml b/BTCPayServer/Views/Server/LndServices.cshtml index 9f547bd61..258ac1149 100644 --- a/BTCPayServer/Views/Server/LndServices.cshtml +++ b/BTCPayServer/Views/Server/LndServices.cshtml @@ -89,9 +89,16 @@ @if (Model.RestrictedMacaroon != null) { @*

*@ + + + *@ + } + @if (Model.GRPCSSLCipherSuites != null) + { +
+ + +
} @if (Model.CertificateThumbprint != null) { From 57324345ac89e01bbabbd5293b0db4939eaa65ac Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 16:24:36 +0900 Subject: [PATCH 03/18] Remove remaining of RestrictedMacaroon --- BTCPayServer/BTCPayServer.csproj | 2 +- BTCPayServer/Controllers/ServerController.cs | 18 ------------------ .../Services/LightningConfigurationProvider.cs | 2 -- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index 36e7d9a28..6ea7245bf 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -33,7 +33,7 @@ - + diff --git a/BTCPayServer/Controllers/ServerController.cs b/BTCPayServer/Controllers/ServerController.cs index f5d61b263..96d6774f0 100644 --- a/BTCPayServer/Controllers/ServerController.cs +++ b/BTCPayServer/Controllers/ServerController.cs @@ -536,10 +536,6 @@ namespace BTCPayServer.Controllers { model.Macaroon = Encoders.Hex.EncodeData(external.Macaroon); } - if (external.RestrictedMacaroon != null) - { - model.RestrictedMacaroon = Encoders.Hex.EncodeData(external.RestrictedMacaroon); - } if (nonce != null) { @@ -588,7 +584,6 @@ namespace BTCPayServer.Controllers conf.Port = external.BaseUri.Port; conf.SSL = external.BaseUri.Scheme == "https"; conf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); - conf.RestrictedMacaroon = external.RestrictedMacaroon == null ? null : Encoders.Hex.EncodeData(external.RestrictedMacaroon); conf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); confs.Configurations.Add(conf); } @@ -600,7 +595,6 @@ namespace BTCPayServer.Controllers restconf.CryptoCode = cryptoCode; restconf.Uri = external.BaseUri.AbsoluteUri; restconf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); - restconf.RestrictedMacaroon = external.RestrictedMacaroon == null ? null : Encoders.Hex.EncodeData(external.RestrictedMacaroon); restconf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); confs.Configurations.Add(restconf); } @@ -629,18 +623,6 @@ namespace BTCPayServer.Controllers return null; } } - if (connectionString.RestrictedMacaroonFilePath != null) - { - try - { - connectionString.RestrictedMacaroon = System.IO.File.ReadAllBytes(connectionString.RestrictedMacaroonFilePath); - } - catch - { - Logs.Configuration.LogWarning($"{cryptoCode}: The restrictedmacaroon file path of the external LND grpc config was not found ({connectionString.RestrictedMacaroonFilePath})"); - } - connectionString.RestrictedMacaroonFilePath = null; - } return connectionString; } diff --git a/BTCPayServer/Services/LightningConfigurationProvider.cs b/BTCPayServer/Services/LightningConfigurationProvider.cs index cb7842af3..87bedef1d 100644 --- a/BTCPayServer/Services/LightningConfigurationProvider.cs +++ b/BTCPayServer/Services/LightningConfigurationProvider.cs @@ -51,7 +51,6 @@ namespace BTCPayServer.Services public bool SSL { get; set; } public string CertificateThumbprint { get; set; } public string Macaroon { get; set; } - public string RestrictedMacaroon { get; set; } } public class LNDRestConfiguration { @@ -61,6 +60,5 @@ namespace BTCPayServer.Services public string Uri { get; set; } public string Macaroon { get; set; } public string CertificateThumbprint { get; set; } - public string RestrictedMacaroon { get; set; } } } From e80593fb7b22cd70a0eef87cfb64d73c8a25943c Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 16:52:04 +0900 Subject: [PATCH 04/18] Expose LND's other macaroon if possible --- BTCPayServer/Controllers/Macaroons.cs | 57 +++++++++++++++++++ BTCPayServer/Controllers/ServerController.cs | 40 +++++++------ .../LndGrpcServicesViewModel.cs | 4 +- .../LightningConfigurationProvider.cs | 22 ++++--- BTCPayServer/Views/Server/LndServices.cshtml | 24 ++++++-- 5 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 BTCPayServer/Controllers/Macaroons.cs diff --git a/BTCPayServer/Controllers/Macaroons.cs b/BTCPayServer/Controllers/Macaroons.cs new file mode 100644 index 000000000..0a87fd6e6 --- /dev/null +++ b/BTCPayServer/Controllers/Macaroons.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace BTCPayServer.Controllers +{ + public class Macaroons + { + public class Macaroon + { + public Macaroon(byte[] bytes) + { + Bytes = bytes; + Hex = NBitcoin.DataEncoders.Encoders.Hex.EncodeData(bytes); + } + + public string Hex { get; set; } + public byte[] Bytes { get; set; } + } + public static async Task GetFromDirectoryAsync(string directoryPath) + { + if (directoryPath == null) + throw new ArgumentNullException(nameof(directoryPath)); + Macaroons macaroons = new Macaroons(); + if (!Directory.Exists(directoryPath)) + return macaroons; + foreach(var file in Directory.GetFiles("*.macaroon")) + { + try + { + switch (Path.GetFileName(file)) + { + case "admin.macaroon": + macaroons.AdminMacaroon = new Macaroon(await File.ReadAllBytesAsync(file)); + break; + case "readonly.macaroon": + macaroons.ReadonlyMacaroon = new Macaroon(await File.ReadAllBytesAsync(file)); + break; + case "invoice.macaroon": + macaroons.InvoiceMacaroon = new Macaroon(await File.ReadAllBytesAsync(file)); + break; + default: + break; + } + } + catch { } + } + return macaroons; + } + public Macaroon ReadonlyMacaroon { get; set; } + + public Macaroon InvoiceMacaroon { get; set; } + public Macaroon AdminMacaroon { get; set; } + } +} diff --git a/BTCPayServer/Controllers/ServerController.cs b/BTCPayServer/Controllers/ServerController.cs index 96d6774f0..7aab0c07b 100644 --- a/BTCPayServer/Controllers/ServerController.cs +++ b/BTCPayServer/Controllers/ServerController.cs @@ -504,7 +504,7 @@ namespace BTCPayServer.Controllers } [Route("server/services/lnd/{cryptoCode}/{index}")] - public IActionResult LndServices(string cryptoCode, int index, uint? nonce) + public async Task LndServices(string cryptoCode, int index, uint? nonce) { if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud)) { @@ -536,6 +536,10 @@ namespace BTCPayServer.Controllers { model.Macaroon = Encoders.Hex.EncodeData(external.Macaroon); } + var macaroons = external.MacaroonDirectoryPath == null ? null : await Macaroons.GetFromDirectoryAsync(external.MacaroonDirectoryPath); + model.AdminMacaroon = macaroons?.AdminMacaroon?.Hex; + model.InvoiceMacaroon = macaroons?.InvoiceMacaroon?.Hex; + model.ReadonlyMacaroon = macaroons?.ReadonlyMacaroon?.Hex; if (nonce != null) { @@ -568,36 +572,40 @@ namespace BTCPayServer.Controllers [Route("server/services/lnd/{cryptoCode}/{index}")] [HttpPost] - public IActionResult LndServicesPost(string cryptoCode, int index) + public async Task LndServicesPost(string cryptoCode, int index) { var external = GetExternalLndConnectionString(cryptoCode, index); if (external == null) return NotFound(); LightningConfigurations confs = new LightningConfigurations(); + var macaroons = external.MacaroonDirectoryPath == null ? null : await Macaroons.GetFromDirectoryAsync(external.MacaroonDirectoryPath); if (external.ConnectionType == LightningConnectionType.LndGRPC) { - LightningConfiguration conf = new LightningConfiguration(); - conf.Type = "grpc"; - conf.ChainType = _Options.NetworkType.ToString(); - conf.CryptoCode = cryptoCode; - conf.Host = external.BaseUri.DnsSafeHost; - conf.Port = external.BaseUri.Port; - conf.SSL = external.BaseUri.Scheme == "https"; - conf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); - conf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); - confs.Configurations.Add(conf); + LightningConfiguration grpcConf = new LightningConfiguration(); + grpcConf.Type = "grpc"; + grpcConf.Host = external.BaseUri.DnsSafeHost; + grpcConf.Port = external.BaseUri.Port; + grpcConf.SSL = external.BaseUri.Scheme == "https"; + confs.Configurations.Add(grpcConf); } else if (external.ConnectionType == LightningConnectionType.LndREST) { var restconf = new LNDRestConfiguration(); restconf.Type = "lnd-rest"; - restconf.ChainType = _Options.NetworkType.ToString(); - restconf.CryptoCode = cryptoCode; restconf.Uri = external.BaseUri.AbsoluteUri; - restconf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); - restconf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); confs.Configurations.Add(restconf); } + else + throw new NotSupportedException(external.ConnectionType.ToString()); + var commonConf = (LNDConfiguration)confs.Configurations[confs.Configurations.Count - 1]; + commonConf.ChainType = _Options.NetworkType.ToString(); + commonConf.CryptoCode = cryptoCode; + commonConf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); + commonConf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); + commonConf.AdminMacaroon = macaroons?.AdminMacaroon?.Hex; + commonConf.ReadonlyMacaroon = macaroons?.ReadonlyMacaroon?.Hex; + commonConf.InvoiceMacaroon = macaroons?.InvoiceMacaroon?.Hex; + var nonce = RandomUtils.GetUInt32(); var configKey = GetConfigKey("lnd", cryptoCode, index, nonce); _LnConfigProvider.KeepConfig(configKey, confs); diff --git a/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs b/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs index 619463f35..54f33dbd8 100644 --- a/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs +++ b/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs @@ -11,7 +11,9 @@ namespace BTCPayServer.Models.ServerViewModels public string Host { get; set; } public bool SSL { get; set; } public string Macaroon { get; set; } - public string RestrictedMacaroon { get; set; } + public string AdminMacaroon { get; set; } + public string ReadonlyMacaroon { get; set; } + public string InvoiceMacaroon { get; set; } public string CertificateThumbprint { get; set; } [Display(Name = "GRPC SSL Cipher suite (GRPC_SSL_CIPHER_SUITES)")] public string GRPCSSLCipherSuites { get; set; } diff --git a/BTCPayServer/Services/LightningConfigurationProvider.cs b/BTCPayServer/Services/LightningConfigurationProvider.cs index 87bedef1d..8bd98bdd4 100644 --- a/BTCPayServer/Services/LightningConfigurationProvider.cs +++ b/BTCPayServer/Services/LightningConfigurationProvider.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NBitcoin; +using NBitcoin.DataEncoders; namespace BTCPayServer.Services { @@ -27,9 +28,9 @@ namespace BTCPayServer.Services private void CleanExpired() { - foreach(var item in _Map) + foreach (var item in _Map) { - if(item.Value.expiration < DateTimeOffset.UtcNow) + if (item.Value.expiration < DateTimeOffset.UtcNow) { _Map.TryRemove(item.Key, out var unused); } @@ -41,24 +42,29 @@ namespace BTCPayServer.Services { public List Configurations { get; set; } = new List(); } - public class LightningConfiguration + + public class LNDConfiguration { public string ChainType { get; set; } public string Type { get; set; } public string CryptoCode { get; set; } + public string CertificateThumbprint { get; set; } + public string Macaroon { get; set; } + public string AdminMacaroon { get; set; } + public string ReadonlyMacaroon { get; set; } + public string InvoiceMacaroon { get; set; } + } + public class LightningConfiguration : LNDConfiguration + { public string Host { get; set; } public int Port { get; set; } public bool SSL { get; set; } - public string CertificateThumbprint { get; set; } - public string Macaroon { get; set; } } - public class LNDRestConfiguration + public class LNDRestConfiguration : LNDConfiguration { public string ChainType { get; set; } public string Type { get; set; } public string CryptoCode { get; set; } public string Uri { get; set; } - public string Macaroon { get; set; } - public string CertificateThumbprint { get; set; } } } diff --git a/BTCPayServer/Views/Server/LndServices.cshtml b/BTCPayServer/Views/Server/LndServices.cshtml index 258ac1149..dd644359e 100644 --- a/BTCPayServer/Views/Server/LndServices.cshtml +++ b/BTCPayServer/Views/Server/LndServices.cshtml @@ -86,12 +86,26 @@ } - @if (Model.RestrictedMacaroon != null) + @if (Model.AdminMacaroon != null) { - @*
- - -
*@ +
+ + +
+ } + @if (Model.InvoiceMacaroon != null) + { +
+ + +
+ } + @if (Model.ReadonlyMacaroon != null) + { +
+ + +
} @if (Model.GRPCSSLCipherSuites != null) { From f56c23009acbc138db7aea84b783381aad4ea1d7 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 16:57:59 +0900 Subject: [PATCH 05/18] bump --- BTCPayServer/BTCPayServer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index 6ea7245bf..db8376305 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -2,7 +2,7 @@ Exe netcoreapp2.1 - 1.0.3.31 + 1.0.3.32 NU1701,CA1816,CA1308,CA1810,CA2208 From 3f6ff2532213af719972723fcf75b47146776f5c Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 17:00:30 +0900 Subject: [PATCH 06/18] update es-ES --- BTCPayServer/wwwroot/locales/es-ES.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BTCPayServer/wwwroot/locales/es-ES.json b/BTCPayServer/wwwroot/locales/es-ES.json index b90d88808..a528f6afa 100644 --- a/BTCPayServer/wwwroot/locales/es-ES.json +++ b/BTCPayServer/wwwroot/locales/es-ES.json @@ -22,12 +22,12 @@ "Amount": "Cantidad", "Address": "Dirección", "Copied": "Copiado", - "ConversionTab_BodyTop": "Puedes pagar {{btcDue}} {{cryptoCode}} usando Altcoins que este comercio no soporta directamente.", + "ConversionTab_BodyTop": "Puedes pagar {{btcDue}} {{cryptoCode}} usando altcoins que este comercio no soporta directamente.", "ConversionTab_BodyDesc": "Este servicio es provisto por terceros. Ten en cuenta que no tenemos control sobre cómo estos terceros envían los fondos. La factura solo se marcará como pagada una vez se reciban los fondos en la cadena de bloques de {{cryptoCode}} .", "ConversionTab_CalculateAmount_Error": "Reintentar", "ConversionTab_LoadCurrencies_Error": "Reintentar", "ConversionTab_Lightning": "No hay proveedores de conversión disponibles para los pagos de Lightning Network.", - "ConversionTab_CurrencyList_Select_Option": "Por favor selecciona el tipo de moneda que de desea cambiar", + "ConversionTab_CurrencyList_Select_Option": "Selecciona la moneda a convertir", "Invoice expiring soon...": "La factura expira pronto...", "Invoice expired": "La factura expiró", "What happened?": "¿Qué sucedió?", From 47ef7661d8e38712a8c8e84e406ce01cbd4b1dc5 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 17:08:32 +0900 Subject: [PATCH 07/18] Fix search for macaroon --- BTCPayServer/Controllers/Macaroons.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer/Controllers/Macaroons.cs b/BTCPayServer/Controllers/Macaroons.cs index 0a87fd6e6..08eb369e8 100644 --- a/BTCPayServer/Controllers/Macaroons.cs +++ b/BTCPayServer/Controllers/Macaroons.cs @@ -26,7 +26,7 @@ namespace BTCPayServer.Controllers Macaroons macaroons = new Macaroons(); if (!Directory.Exists(directoryPath)) return macaroons; - foreach(var file in Directory.GetFiles("*.macaroon")) + foreach(var file in Directory.GetFiles(directoryPath, "*.macaroon")) { try { From 27fa2d5b69b06d2a817136b6f66317e9a1d20013 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Thu, 20 Dec 2018 09:21:20 +0100 Subject: [PATCH 08/18] do not add ln payment if amount couldn't be parsed --- BTCPayServer/Payments/Lightning/LightningListener.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BTCPayServer/Payments/Lightning/LightningListener.cs b/BTCPayServer/Payments/Lightning/LightningListener.cs index 1fef6f9c6..abf56011b 100644 --- a/BTCPayServer/Payments/Lightning/LightningListener.cs +++ b/BTCPayServer/Payments/Lightning/LightningListener.cs @@ -156,7 +156,8 @@ namespace BTCPayServer.Payments.Lightning if (notification.Id == listenedInvoice.PaymentMethodDetails.InvoiceId && notification.BOLT11 == listenedInvoice.PaymentMethodDetails.BOLT11) { - if (notification.Status == LightningInvoiceStatus.Paid && notification.PaidAt.HasValue) + if (notification.Status == LightningInvoiceStatus.Paid && + notification.PaidAt.HasValue && notification.Amount != null) { await AddPayment(network, notification, listenedInvoice); if (DoneListening(listenedInvoice)) From 4bf22286753b416718f9fca2aa5f18eddee621b9 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 18:35:32 +0900 Subject: [PATCH 09/18] Show test logs in CircleCI --- BTCPayServer.Tests/docker-entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer.Tests/docker-entrypoint.sh b/BTCPayServer.Tests/docker-entrypoint.sh index ec8b479b5..7a7c29dcc 100755 --- a/BTCPayServer.Tests/docker-entrypoint.sh +++ b/BTCPayServer.Tests/docker-entrypoint.sh @@ -2,4 +2,4 @@ set -e dotnet test --filter Fast=Fast --no-build -dotnet test --filter Integration=Integration --no-build +dotnet test --filter Integration=Integration --no-build -v n From 5f16fb46688338ccba0b7408a5179b09852ae4a7 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 18:44:39 +0900 Subject: [PATCH 10/18] report slow tests --- BTCPayServer.Tests/xunit.runner.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/xunit.runner.json b/BTCPayServer.Tests/xunit.runner.json index dc14f82b1..35e95c9c8 100644 --- a/BTCPayServer.Tests/xunit.runner.json +++ b/BTCPayServer.Tests/xunit.runner.json @@ -1,3 +1,4 @@ { - "parallelizeTestCollections": false -} \ No newline at end of file + "parallelizeTestCollections": false, + "longRunningTestSeconds": 60 +} From 4d7015294e8515c3340744849bcfe0f5d06f1c88 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 20:12:36 +0900 Subject: [PATCH 11/18] Fix configuration of lnd rest --- BTCPayServer/BTCPayServer.csproj | 2 +- BTCPayServer/Services/LightningConfigurationProvider.cs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index db8376305..eab5a7643 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -2,7 +2,7 @@ Exe netcoreapp2.1 - 1.0.3.32 + 1.0.3.33 NU1701,CA1816,CA1308,CA1810,CA2208 diff --git a/BTCPayServer/Services/LightningConfigurationProvider.cs b/BTCPayServer/Services/LightningConfigurationProvider.cs index 8bd98bdd4..36eeff879 100644 --- a/BTCPayServer/Services/LightningConfigurationProvider.cs +++ b/BTCPayServer/Services/LightningConfigurationProvider.cs @@ -62,9 +62,6 @@ namespace BTCPayServer.Services } public class LNDRestConfiguration : LNDConfiguration { - public string ChainType { get; set; } - public string Type { get; set; } - public string CryptoCode { get; set; } public string Uri { get; set; } } } From 361d494cde3ae9aab4451a63d3a559f3df661a25 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 20:24:06 +0900 Subject: [PATCH 12/18] Accept cookiefilepath as alternative to cookiefile for spark connection string --- BTCPayServer/Configuration/SparkConnectionString.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/BTCPayServer/Configuration/SparkConnectionString.cs b/BTCPayServer/Configuration/SparkConnectionString.cs index 636f20431..5a0188039 100644 --- a/BTCPayServer/Configuration/SparkConnectionString.cs +++ b/BTCPayServer/Configuration/SparkConnectionString.cs @@ -31,6 +31,7 @@ namespace BTCPayServer.Configuration resultTemp.Server = new Uri(kv[1], UriKind.Absolute); break; case "cookiefile": + case "cookiefilepath": if (resultTemp.CookeFile != null) return false; resultTemp.CookeFile = kv[1]; From 9dcf16e8193f2454d695302beefbc3145e773869 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 21:00:06 +0900 Subject: [PATCH 13/18] Add xunit diagnostic message --- BTCPayServer.Tests/xunit.runner.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BTCPayServer.Tests/xunit.runner.json b/BTCPayServer.Tests/xunit.runner.json index 35e95c9c8..3b632dd96 100644 --- a/BTCPayServer.Tests/xunit.runner.json +++ b/BTCPayServer.Tests/xunit.runner.json @@ -1,4 +1,5 @@ { "parallelizeTestCollections": false, - "longRunningTestSeconds": 60 + "longRunningTestSeconds": 60, + "diagnosticMessages": true } From 2e04c5e39cbdabdb204eb868d9b512896482b0ee Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 21:20:30 +0900 Subject: [PATCH 14/18] Update docker-compose test --- BTCPayServer.Tests/docker-compose.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index ba03e445e..7456fa4c5 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -93,12 +93,13 @@ services: - bitcoind - litecoind + bitcoind: + restart: unless-stopped image: btcpayserver/bitcoin:0.17.0 environment: - BITCOIN_NETWORK: regtest - BITCOIN_EXTRA_ARGS: | - deprecatedrpc=signrawtransaction + BITCOIN_NETWORK:regtest + BITCOIN_EXTRA_ARGS: |- rpcuser=ceiwHEbqWI83 rpcpassword=DwubwWsoo3 rpcport=43782 @@ -108,7 +109,6 @@ services: zmqpubrawtx=tcp://0.0.0.0:28333 ports: - "43782:43782" - - "28332:28332" expose: - "43782" # RPC - "39388" # P2P @@ -188,13 +188,13 @@ services: - bitcoind litecoind: + restart: unless-stopped image: nicolasdorier/docker-litecoin:0.16.3 environment: - BITCOIN_EXTRA_ARGS: | + BITCOIN_EXTRA_ARGS: |- rpcuser=ceiwHEbqWI83 rpcpassword=DwubwWsoo3 regtest=1 - server=1 rpcport=43782 port=39388 whitelist=0.0.0.0/0 @@ -221,13 +221,16 @@ services: - MYSQL_ALLOW_EMPTY_PASSWORD=yes merchant_lnd: - image: btcpayserver/lnd:0.5-beta-2 + image: btcpayserver/lnd:v0.5.1-beta restart: unless-stopped environment: LND_CHAIN: "btc" LND_ENVIRONMENT: "regtest" + LND_EXPLORERURL: "http://nbxplorer:32838/" LND_EXTRA_ARGS: | restlisten=0.0.0.0:8080 + rpclisten=127.0.0.1:10008 + rpclisten=0.0.0.0:10009 bitcoin.node=bitcoind bitcoind.rpchost=bitcoind:43782 bitcoind.zmqpubrawblock=tcp://bitcoind:28332 @@ -248,13 +251,16 @@ services: - bitcoind customer_lnd: - image: btcpayserver/lnd:0.5-beta-2 + image: btcpayserver/lnd:v0.5.1-beta restart: unless-stopped environment: LND_CHAIN: "btc" LND_ENVIRONMENT: "regtest" + LND_EXPLORERURL: "http://nbxplorer:32838/" LND_EXTRA_ARGS: | restlisten=0.0.0.0:8080 + rpclisten=127.0.0.1:10008 + rpclisten=0.0.0.0:10009 bitcoin.node=bitcoind bitcoind.rpchost=bitcoind:43782 bitcoind.zmqpubrawblock=tcp://bitcoind:28332 From c35bf2f483fb818ba85e6f4d7aabd89044d132a1 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 21:23:24 +0900 Subject: [PATCH 15/18] fix docker compose --- BTCPayServer.Tests/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index 7456fa4c5..cb2000756 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -98,7 +98,7 @@ services: restart: unless-stopped image: btcpayserver/bitcoin:0.17.0 environment: - BITCOIN_NETWORK:regtest + BITCOIN_NETWORK: regtest BITCOIN_EXTRA_ARGS: |- rpcuser=ceiwHEbqWI83 rpcpassword=DwubwWsoo3 From bac2db5cda4d53556c23817782502b20d028fb67 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 21:27:08 +0900 Subject: [PATCH 16/18] Add timeout to lightning tests --- BTCPayServer.Tests/UnitTest1.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index d8f9b24d1..eab823615 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -355,7 +355,7 @@ namespace BTCPayServer.Tests } } - [Fact] + [Fact(Timeout = 60 * 1000)] [Trait("Integration", "Integration")] public async Task CanSetLightningServer() { @@ -407,7 +407,7 @@ namespace BTCPayServer.Tests await ProcessLightningPayment(LightningConnectionType.Charge); } - [Fact] + [Fact(Timeout = 60 * 1000)] [Trait("Integration", "Integration")] public async Task CanSendLightningPaymentLnd() { @@ -1362,7 +1362,7 @@ namespace BTCPayServer.Tests } } - [Fact] + [Fact(Timeout = 60 * 1000)] [Trait("Integration", "Integration")] public async Task CanSetPaymentMethodLimits() { From d0f585df9d901eedde197904ab126920f1be46ff Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 21:34:09 +0900 Subject: [PATCH 17/18] fix tests --- BTCPayServer.Tests/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml index cb2000756..e7089172d 100644 --- a/BTCPayServer.Tests/docker-compose.yml +++ b/BTCPayServer.Tests/docker-compose.yml @@ -107,6 +107,7 @@ services: whitelist=0.0.0.0/0 zmqpubrawblock=tcp://0.0.0.0:28332 zmqpubrawtx=tcp://0.0.0.0:28333 + deprecatedrpc=signrawtransaction ports: - "43782:43782" expose: From 9c99ffae57f22e75b71a5d763bf26eb1d957ccc0 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Thu, 20 Dec 2018 22:40:32 +0900 Subject: [PATCH 18/18] Lightning charge integration --- BTCPayServer/BTCPayServer.csproj | 3 + .../Configuration/BTCPayServerOptions.cs | 28 +++++++-- .../Configuration/DefaultConfiguration.cs | 3 +- .../Configuration/External/ExternalCharge.cs | 19 ++++++ BTCPayServer/Controllers/ServerController.cs | 51 +++++++++++++++- .../ChargeServiceViewModel.cs | 14 +++++ BTCPayServer/Properties/launchSettings.json | 1 + .../Server/LightningChargeServices.cshtml | 60 +++++++++++++++++++ 8 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 BTCPayServer/Configuration/External/ExternalCharge.cs create mode 100644 BTCPayServer/Models/ServerViewModels/ChargeServiceViewModel.cs create mode 100644 BTCPayServer/Views/Server/LightningChargeServices.cshtml diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index eab5a7643..73239a3ec 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -136,6 +136,9 @@ $(IncludeRazorContentInPack) + + $(IncludeRazorContentInPack) + $(IncludeRazorContentInPack) diff --git a/BTCPayServer/Configuration/BTCPayServerOptions.cs b/BTCPayServer/Configuration/BTCPayServerOptions.cs index 99c7aea30..d657f6944 100644 --- a/BTCPayServer/Configuration/BTCPayServerOptions.cs +++ b/BTCPayServer/Configuration/BTCPayServerOptions.cs @@ -37,8 +37,8 @@ namespace BTCPayServer.Configuration { get; private set; - } - + } + public string LogFile { get; @@ -68,7 +68,7 @@ namespace BTCPayServer.Configuration public static LogEventLevel GetDebugLogLevel(IConfiguration configuration) { var raw = configuration.GetValue("debugloglevel", nameof(LogEventLevel.Debug)); - return (LogEventLevel)Enum.Parse(typeof(LogEventLevel), raw, true); + return (LogEventLevel)Enum.Parse(typeof(LogEventLevel), raw, true); } public void LoadArgs(IConfiguration conf) @@ -139,7 +139,7 @@ namespace BTCPayServer.Configuration externalLnd($"{net.CryptoCode}.external.lnd.rest", "lnd-rest"); var spark = conf.GetOrDefault($"{net.CryptoCode}.external.spark", string.Empty); - if(spark.Length != 0) + if (spark.Length != 0) { if (!SparkConnectionString.TryParse(spark, out var connectionString)) { @@ -148,14 +148,30 @@ namespace BTCPayServer.Configuration } ExternalServicesByCryptoCode.Add(net.CryptoCode, new ExternalSpark(connectionString)); } + + var charge = conf.GetOrDefault($"{net.CryptoCode}.external.charge", string.Empty); + if (charge.Length != 0) + { + if (!LightningConnectionString.TryParse(charge, false, out var chargeConnectionString, out var chargeError)) + LightningConnectionString.TryParse("type=charge;" + charge, false, out chargeConnectionString, out chargeError); + + if(chargeConnectionString == null || chargeConnectionString.ConnectionType != LightningConnectionType.Charge) + { + throw new ConfigException($"Invalid setting {net.CryptoCode}.external.charge, " + Environment.NewLine + + $"lightning charge server: 'type=charge;server=https://charge.example.com;api-token=2abdf302...'" + Environment.NewLine + + $"lightning charge server: 'type=charge;server=https://charge.example.com;cookiefilepath=/root/.charge/.cookie'" + Environment.NewLine + + chargeError ?? string.Empty); + } + ExternalServicesByCryptoCode.Add(net.CryptoCode, new ExternalCharge(chargeConnectionString)); + } } Logs.Configuration.LogInformation("Supported chains: " + String.Join(',', supportedChains.ToArray())); var services = conf.GetOrDefault("externalservices", null); - if(services != null) + if (services != null) { - foreach(var service in services.Split(new[] { ';', ',' }) + foreach (var service in services.Split(new[] { ';', ',' }) .Select(p => p.Split(':')) .Where(p => p.Length == 2) .Select(p => (Name: p[0], Link: p[1]))) diff --git a/BTCPayServer/Configuration/DefaultConfiguration.cs b/BTCPayServer/Configuration/DefaultConfiguration.cs index 9e49c5d87..6717312d7 100644 --- a/BTCPayServer/Configuration/DefaultConfiguration.cs +++ b/BTCPayServer/Configuration/DefaultConfiguration.cs @@ -50,7 +50,8 @@ namespace BTCPayServer.Configuration app.Option($"--{crypto}explorercookiefile", $"Path to the cookie file (default: {network.NBXplorerNetwork.DefaultSettings.DefaultCookieFile})", CommandOptionType.SingleValue); app.Option($"--{crypto}lightning", $"Easy configuration of lightning for the server administrator: Must be a UNIX socket of c-lightning (lightning-rpc) or URL to a charge server (default: empty)", CommandOptionType.SingleValue); app.Option($"--{crypto}externallndgrpc", $"The LND gRPC configuration BTCPay will expose to easily connect to the internal lnd wallet from Zap wallet (default: empty)", CommandOptionType.SingleValue); - app.Option($"--{crypto}externalspark", $"The connection string to spark server (default: empty)", CommandOptionType.SingleValue); + app.Option($"--{crypto}externalspark", $"Show spark information in Server settings / Server. The connection string to spark server (default: empty)", CommandOptionType.SingleValue); + app.Option($"--{crypto}externalcharge", $"Show lightning charge information in Server settings/Server. The connection string to charge server (default: empty)", CommandOptionType.SingleValue); } return app; } diff --git a/BTCPayServer/Configuration/External/ExternalCharge.cs b/BTCPayServer/Configuration/External/ExternalCharge.cs new file mode 100644 index 000000000..03b8d5c86 --- /dev/null +++ b/BTCPayServer/Configuration/External/ExternalCharge.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BTCPayServer.Lightning; + +namespace BTCPayServer.Configuration.External +{ + public class ExternalCharge : ExternalService + { + public ExternalCharge(LightningConnectionString connectionString) + { + if (connectionString == null) + throw new ArgumentNullException(nameof(connectionString)); + ConnectionString = connectionString; + } + public LightningConnectionString ConnectionString { get; } + } +} diff --git a/BTCPayServer/Controllers/ServerController.cs b/BTCPayServer/Controllers/ServerController.cs index 7aab0c07b..3c5e404c0 100644 --- a/BTCPayServer/Controllers/ServerController.cs +++ b/BTCPayServer/Controllers/ServerController.cs @@ -449,6 +449,16 @@ namespace BTCPayServer.Controllers Index = i++, }); } + foreach (var chargeService in _Options.ExternalServicesByCryptoCode.GetServices(cryptoCode)) + { + result.LNDServices.Add(new ServicesViewModel.LNDServiceViewModel() + { + Crypto = cryptoCode, + Type = "Lightning charge server", + Action = nameof(LightningChargeServices), + Index = i++, + }); + } } foreach(var externalService in _Options.ExternalServices) { @@ -469,6 +479,45 @@ namespace BTCPayServer.Controllers return View(result); } + [Route("server/services/lightning-charge/{cryptoCode}/{index}")] + public async Task LightningChargeServices(string cryptoCode, int index, bool showQR = false) + { + if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud)) + { + StatusMessage = $"Error: {cryptoCode} is not fully synched"; + return RedirectToAction(nameof(Services)); + } + var lightningCharge = _Options.ExternalServicesByCryptoCode.GetServices(cryptoCode).Select(c => c.ConnectionString).FirstOrDefault(); + if (lightningCharge == null) + { + return NotFound(); + } + + ChargeServiceViewModel vm = new ChargeServiceViewModel(); + vm.Uri = lightningCharge.ToUri(false).AbsoluteUri; + vm.APIToken = lightningCharge.Password; + try + { + if (string.IsNullOrEmpty(vm.APIToken) && lightningCharge.CookieFilePath != null) + { + if (lightningCharge.CookieFilePath != "fake") + vm.APIToken = await System.IO.File.ReadAllTextAsync(lightningCharge.CookieFilePath); + else + vm.APIToken = "fake"; + } + var builder = new UriBuilder(lightningCharge.ToUri(false)); + builder.UserName = "api-token"; + builder.Password = vm.APIToken; + vm.AuthenticatedUri = builder.ToString(); + } + catch (Exception ex) + { + StatusMessage = $"Error: {ex.Message}"; + return RedirectToAction(nameof(Services)); + } + return View(vm); + } + [Route("server/services/spark/{cryptoCode}/{index}")] public async Task SparkServices(string cryptoCode, int index, bool showQR = false) { @@ -477,7 +526,7 @@ namespace BTCPayServer.Controllers StatusMessage = $"Error: {cryptoCode} is not fully synched"; return RedirectToAction(nameof(Services)); } - var spark = _Options.ExternalServicesByCryptoCode.GetServices(cryptoCode).Skip(index).Select(c => c.ConnectionString).FirstOrDefault(); + var spark = _Options.ExternalServicesByCryptoCode.GetServices(cryptoCode).Select(c => c.ConnectionString).FirstOrDefault(); if(spark == null) { return NotFound(); diff --git a/BTCPayServer/Models/ServerViewModels/ChargeServiceViewModel.cs b/BTCPayServer/Models/ServerViewModels/ChargeServiceViewModel.cs new file mode 100644 index 000000000..25b8ac4f6 --- /dev/null +++ b/BTCPayServer/Models/ServerViewModels/ChargeServiceViewModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace BTCPayServer.Models.ServerViewModels +{ + public class ChargeServiceViewModel + { + public string Uri { get; set; } + public string APIToken { get; set; } + public string AuthenticatedUri { get; set; } + } +} diff --git a/BTCPayServer/Properties/launchSettings.json b/BTCPayServer/Properties/launchSettings.json index 5bfafb34c..226da05de 100644 --- a/BTCPayServer/Properties/launchSettings.json +++ b/BTCPayServer/Properties/launchSettings.json @@ -30,6 +30,7 @@ "BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true", "BTCPAY_BTCEXTERNALLNDREST": "type=lnd-rest;server=https://lnd:lnd@127.0.0.1:53280/lnd-rest/btc/;allowinsecure=true", "BTCPAY_BTCEXTERNALSPARK": "server=https://127.0.0.1:53280/spark/btc/;cookiefile=fake", + "BTCPAY_BTCEXTERNALCHARGE": "server=https://127.0.0.1:53280/spark/btc/;cookiefilepath=fake", "BTCPAY_BTCEXPLORERURL": "http://127.0.0.1:32838/", "ASPNETCORE_ENVIRONMENT": "Development", "BTCPAY_CHAINS": "btc,ltc", diff --git a/BTCPayServer/Views/Server/LightningChargeServices.cshtml b/BTCPayServer/Views/Server/LightningChargeServices.cshtml new file mode 100644 index 000000000..6bc4e9946 --- /dev/null +++ b/BTCPayServer/Views/Server/LightningChargeServices.cshtml @@ -0,0 +1,60 @@ +@model ChargeServiceViewModel +@{ + ViewData.SetActivePageAndTitle(ServerNavPages.Services); +} + + +

Lightning charge service

+ + +
+
+
+
+
+ +
+
+
+

+ Lightning charge is a simple API for invoicing on lightning network, you can use it with several plugins: +

    +
  • WooCommerce Lightning Gateway: A comprehensive e-commerce application that integrates with stock-management and order-tracking systems
  • +
  • Nanopos: A simple point-of-sale system for fixed-price goods
  • +
  • FileBazaar: A system for selling files such as documents, images, and videos
  • +
  • Lightning Publisher for WordPress: A patronage model for unlocking WordPress blog entries
  • +
  • Paypercall: A programmer’s toolkit for Lightning that enables micropayments for individual API calls
  • +
  • Ifpaytt: An extension of paypercall that allows web developers using IFTTT to request payments for service usage
  • +
  • Lightning Jukebox: A fun demo that reimagines a classic technology for the Lightning Network
  • +
  • Nanotip: The simple tip jar, rebuilt to issue Lightning Network invoices
  • +
+

+
+
+
+
+
+

Credentials

+ @if (Model.Uri != null) + { +
+ + +
+ } + @if (Model.APIToken != null) + { +
+ + +
+ } + @if (Model.AuthenticatedUri != null) + { +
+ + +
+ } +
+