From a566cb66fdffd877c951b85ace3232bc5c3af8ba Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Wed, 20 Sep 2023 12:22:17 -0400 Subject: [PATCH 01/37] remove transactions from consensus struct --- crates/hotshot/src/lib.rs | 21 -------------- crates/hotshot/src/tasks/mod.rs | 4 ++- crates/task-impls/src/transactions.rs | 41 +++++++++++++++++---------- crates/types/src/consensus.rs | 14 --------- 4 files changed, 29 insertions(+), 51 deletions(-) diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index b09ea6235d..38c05e19be 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -133,11 +133,6 @@ pub struct SystemContextInner> { /// a reference to the metrics that the implementor is using. _metrics: Box, - /// Transactions - /// (this is shared btwn hotshot and `Consensus`) - transactions: - Arc, TYPES::Transaction>>>, - /// The hotstuff implementation consensus: Arc>>, @@ -219,8 +214,6 @@ impl> SystemContext { state_map, cur_view: start_view, last_decided_view: anchored_leaf.get_view_number(), - transactions: Arc::default(), - seen_transactions: HashSet::new(), saved_leaves, saved_blocks, // TODO this is incorrect @@ -231,17 +224,14 @@ impl> SystemContext { invalid_qc: 0, }; let consensus = Arc::new(RwLock::new(consensus)); - let txns = consensus.read().await.get_transactions(); let inner: Arc> = Arc::new(SystemContextInner { id: nonce, channel_maps: I::new_channel_maps(start_view), consensus, - transactions: txns, public_key, private_key, config, - // networking, storage, exchanges: Arc::new(exchanges), event_sender: RwLock::default(), @@ -546,11 +536,6 @@ impl> SystemContext { /// [`HotShot`] implementations that depend on [`TYPES::ConsensusType`]. #[async_trait] pub trait HotShotType> { - /// Get the [`transactions`] field of [`HotShot`]. - fn transactions( - &self, - ) -> &Arc, TYPES::Transaction>>>; - /// Get the [`hotstuff`] field of [`HotShot`]. fn consensus(&self) -> &Arc>>; @@ -684,12 +669,6 @@ where Membership = MEMBERSHIP, > + 'static, { - fn transactions( - &self, - ) -> &Arc, TYPES::Transaction>>> { - &self.inner.transactions - } - fn consensus(&self) -> &Arc>> { &self.inner.consensus } diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 619fdb6d59..a2e68528f4 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -43,7 +43,7 @@ use hotshot_types::{ vote::{ViewSyncData, VoteType}, }; use serde::Serialize; -use std::{collections::HashMap, marker::PhantomData, sync::Arc, time::Duration}; +use std::{collections::{HashMap, HashSet}, marker::PhantomData, sync::Arc, time::Duration}; /// event for global event stream #[derive(Clone, Debug)] @@ -441,6 +441,8 @@ where registry: registry.clone(), api: c_api.clone(), consensus: handle.hotshot.get_consensus(), + transactions: Arc::default(), + seen_transactions: HashSet::new(), cur_view: TYPES::Time::new(0), committee_exchange: committee_exchange.into(), event_stream: event_stream.clone(), diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 8609708653..b41604376d 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -1,9 +1,11 @@ use crate::events::SequencingHotShotEvent; +use async_compatibility_layer::async_primitives::subscribable_rwlock::SubscribableRwLock; use async_compatibility_layer::{ art::async_timeout, async_primitives::subscribable_rwlock::ReadView, }; use async_lock::RwLock; use bincode::config::Options; +use commit::Commitment; use commit::Committable; use either::{Either, Left, Right}; use hotshot_task::{ @@ -26,9 +28,16 @@ use hotshot_types::{ }; use hotshot_utils::bincode::bincode_opts; use snafu::Snafu; -use std::{collections::HashSet, sync::Arc, time::Instant}; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::Instant, +}; use tracing::{debug, error, instrument, warn}; +/// A type alias for `HashMap, T>` +type CommitmentMap = HashMap, T>; + #[derive(Snafu, Debug)] /// Error type for consensus tasks pub struct ConsensusTaskError {} @@ -61,6 +70,12 @@ pub struct TransactionTaskState< /// Reference to consensus. Leader will require a read lock on this. pub consensus: Arc>>>, + /// A list of undecided transactions + pub transactions: Arc>>, + + /// A list of transactions we've seen decided, but didn't receive + pub seen_transactions: HashSet>, + /// the committee exchange pub committee_exchange: Arc>, @@ -97,15 +112,14 @@ where ) -> Option { match event { SequencingHotShotEvent::TransactionsRecv(transactions) => { - let mut consensus = self.consensus.write().await; - consensus - .get_transactions() + let consensus = self.consensus.read().await; + self.transactions .modify(|txns| { for transaction in transactions { let size = bincode_opts().serialized_size(&transaction).unwrap_or(0); // If we didn't already know about this transaction, update our mempool metrics. - if !consensus.seen_transactions.remove(&transaction.commit()) + if !self.seen_transactions.remove(&transaction.commit()) && txns.insert(transaction.commit(), transaction).is_none() { consensus.metrics.outstanding_transactions.update(1); @@ -138,17 +152,16 @@ where Right(_) => {} } } - let mut consensus = self.consensus.write().await; - let txns = consensus.transactions.cloned().await; + let consensus = self.consensus.read().await; + let txns = self.transactions.cloned().await; let _ = included_txns.iter().map(|hash| { if !txns.contains_key(hash) { - consensus.seen_transactions.insert(*hash); + self.seen_transactions.insert(*hash); } }); drop(txns); - consensus - .transactions + self.transactions .modify(|txns| { *txns = txns .drain() @@ -255,12 +268,10 @@ where Either::Right(_commitment) => HashSet::new(), }; - let consensus = self.consensus.read().await; - - let receiver = consensus.transactions.subscribe().await; + let receiver = self.transactions.subscribe().await; loop { - let all_txns = consensus.transactions.cloned().await; + let all_txns = self.transactions.cloned().await; debug!("Size of transactions: {}", all_txns.len()); let unclaimed_txns: Vec<_> = all_txns .iter() @@ -290,7 +301,7 @@ where } break; } - let all_txns = consensus.transactions.cloned().await; + let all_txns = self.transactions.cloned().await; let txns: Vec = all_txns .iter() .filter_map(|(txn_hash, txn)| { diff --git a/crates/types/src/consensus.rs b/crates/types/src/consensus.rs index a29c840056..ce27d7a547 100644 --- a/crates/types/src/consensus.rs +++ b/crates/types/src/consensus.rs @@ -2,8 +2,6 @@ pub use crate::traits::node_implementation::ViewQueue; pub use crate::utils::{View, ViewInner}; -use async_compatibility_layer::async_primitives::subscribable_rwlock::SubscribableRwLock; -use std::collections::HashSet; use crate::utils::Terminator; use crate::{ @@ -41,12 +39,6 @@ pub struct Consensus> { /// last view had a successful decide event pub last_decided_view: TYPES::Time, - /// A list of undecided transactions - pub transactions: Arc>>, - - /// A list of transactions we've seen decided, but didn't receive - pub seen_transactions: HashSet>, - /// Map of leaf hash -> leaf /// - contains undecided leaves /// - includes the MOST RECENT decided leaf @@ -264,12 +256,6 @@ impl> Consensus { self.state_map = self.state_map.split_off(&new_anchor_view); } - /// return a clone of the internal storage of unclaimed transactions - #[must_use] - pub fn get_transactions(&self) -> Arc>> { - self.transactions.clone() - } - /// Gets the last decided state /// # Panics /// if the last decided view's state does not exist in the state map From fb690fb9e36b8453d5a75370849defc30725fb71 Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Wed, 20 Sep 2023 12:44:33 -0400 Subject: [PATCH 02/37] linting --- crates/hotshot/src/lib.rs | 6 +++--- crates/hotshot/src/tasks/mod.rs | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index e543f22901..0f317c9410 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -42,12 +42,12 @@ use crate::{ }; use async_compatibility_layer::{ art::{async_spawn, async_spawn_local}, - async_primitives::{broadcast::BroadcastSender, subscribable_rwlock::SubscribableRwLock}, + async_primitives::broadcast::BroadcastSender, channel::UnboundedSender, }; use async_lock::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; use async_trait::async_trait; -use commit::{Commitment, Committable}; +use commit::Committable; use custom_debug::Debug; use hotshot_task::{ event_stream::{ChannelStream, EventStream}, @@ -83,7 +83,7 @@ use hotshot_types::{ }; use snafu::ResultExt; use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{BTreeMap, HashMap}, marker::PhantomData, num::NonZeroUsize, sync::Arc, diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index a2e68528f4..82ea383353 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -43,7 +43,12 @@ use hotshot_types::{ vote::{ViewSyncData, VoteType}, }; use serde::Serialize; -use std::{collections::{HashMap, HashSet}, marker::PhantomData, sync::Arc, time::Duration}; +use std::{ + collections::{HashMap, HashSet}, + marker::PhantomData, + sync::Arc, + time::Duration, +}; /// event for global event stream #[derive(Clone, Debug)] From 6d8f64d1b349e21aa4d627e9c3af46c306b6f333 Mon Sep 17 00:00:00 2001 From: Brendon Fish Date: Wed, 20 Sep 2023 15:10:51 -0400 Subject: [PATCH 03/37] allow more failures in web catchup test --- crates/testing/tests/catchup.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/testing/tests/catchup.rs b/crates/testing/tests/catchup.rs index 9c6bd0bb38..01610f38f2 100644 --- a/crates/testing/tests/catchup.rs +++ b/crates/testing/tests/catchup.rs @@ -164,7 +164,7 @@ async fn test_catchup_one_node() { ..Default::default() }; // only alow for the view which the catchup node hasn't started to fail - metadata.overall_safety_properties.num_failed_views = 1; + metadata.overall_safety_properties.num_failed_views = 5; metadata .gen_launcher::() From 4a29f8f74d750e8b3a02cfda546cae9002fd2f66 Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Wed, 20 Sep 2023 17:49:32 -0400 Subject: [PATCH 04/37] chore: remove Committable from 3 more types (#1789) * VoteMap type param Commitment -> COMMITMENT * VoteAccumulator type param commitment instead of Committable * VoteType remove Committable from type param (this was a big one) --- crates/hotshot/src/tasks/mod.rs | 6 +-- crates/types/src/traits/election.rs | 4 +- crates/types/src/vote.rs | 58 ++++++++++++++++------------- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 619fdb6d59..3f342b68f7 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -5,7 +5,7 @@ use crate::{ QuorumCertificate, SequencingQuorumEx, }; use async_compatibility_layer::art::async_sleep; -use commit::Committable; +use commit::{Commitment, Committable}; use futures::FutureExt; use hotshot_task::{ boxed_sync, @@ -66,7 +66,7 @@ pub async fn add_network_message_task< >, COMMITTABLE: Committable + Serialize + Clone, PROPOSAL: ProposalType, - VOTE: VoteType, + VOTE: VoteType>, MEMBERSHIP: Membership, EXCHANGE: ConsensusExchange< TYPES, @@ -176,7 +176,7 @@ pub async fn add_network_event_task< >, COMMITTABLE: Committable + Serialize + Clone, PROPOSAL: ProposalType, - VOTE: VoteType, + VOTE: VoteType>, MEMBERSHIP: Membership, EXCHANGE: ConsensusExchange< TYPES, diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index 3d152cc85e..fb1ff72a58 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -165,7 +165,7 @@ where TOKEN: VoteToken, { /// `VoteType` that is used in this certificate - type Vote: VoteType; + type Vote: VoteType>; /// `Accumulator` type to accumulate votes. type VoteAccumulator: Accumulator2; @@ -267,7 +267,7 @@ pub trait ConsensusExchange: Send + Sync { type Proposal: ProposalType; /// A vote on a [`Proposal`](Self::Proposal). // TODO ED Make this equal Certificate vote (if possible?) - type Vote: VoteType; + type Vote: VoteType>; /// A [`SignedCertificate`] attesting to a decision taken by the committee. type Certificate: SignedCertificate + Hash diff --git a/crates/types/src/vote.rs b/crates/types/src/vote.rs index ef53bc4018..c470925b54 100644 --- a/crates/types/src/vote.rs +++ b/crates/types/src/vote.rs @@ -28,7 +28,7 @@ use std::{ use tracing::error; /// The vote sent by consensus messages. -pub trait VoteType: +pub trait VoteType Deserialize<'a> + Serialize + Clone>: Debug + Clone + 'static + Serialize + for<'a> Deserialize<'a> + Send + Sync + PartialEq { /// Get the view this vote was cast for @@ -38,7 +38,7 @@ pub trait VoteType EncodedSignature; /// Get the data this vote was signed over - fn get_data(&self) -> VoteData>; + fn get_data(&self) -> VoteData; /// Get the vote token of this vote fn get_vote_token(&self) -> TYPES::VoteTokenType; } @@ -196,7 +196,7 @@ pub enum QuorumVote> { Timeout(TimeoutVote), } -impl VoteType for DAVote { +impl VoteType> for DAVote { fn get_view(&self) -> TYPES::Time { self.current_view } @@ -223,7 +223,7 @@ impl DAVote { } } -impl> VoteType +impl> VoteType> for QuorumVote { fn get_view(&self) -> TYPES::Time { @@ -275,7 +275,7 @@ impl> QuorumVote } } -impl VoteType> for ViewSyncVote { +impl VoteType>> for ViewSyncVote { fn get_view(&self) -> TYPES::Time { match self { ViewSyncVote::PreCommit(v) | ViewSyncVote::Commit(v) | ViewSyncVote::Finalize(v) => { @@ -320,7 +320,7 @@ pub trait Accumulator: Sized { pub trait Accumulator2< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, >: Sized { /// Append 1 vote to the accumulator. If the threshold is not reached, return @@ -338,10 +338,10 @@ pub trait Accumulator2< pub struct DAVoteAccumulator< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > { /// Map of all da signatures accumlated so far - pub da_vote_outcomes: VoteMap, + pub da_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// A quorum's worth of stake, generally 2f + 1 pub success_threshold: NonZeroU64, /// A list of valid signatures for certificate aggregation @@ -355,7 +355,7 @@ pub struct DAVoteAccumulator< impl< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > Accumulator2 for DAVoteAccumulator { fn append( @@ -429,14 +429,14 @@ impl< pub struct QuorumVoteAccumulator< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > { /// Map of all signatures accumlated so far - pub total_vote_outcomes: VoteMap, + pub total_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// Map of all yes signatures accumlated so far - pub yes_vote_outcomes: VoteMap, + pub yes_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// Map of all no signatures accumlated so far - pub no_vote_outcomes: VoteMap, + pub no_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// A quorum's worth of stake, generally 2f + 1 pub success_threshold: NonZeroU64, @@ -453,7 +453,7 @@ pub struct QuorumVoteAccumulator< impl< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > Accumulator2 for QuorumVoteAccumulator { fn append( @@ -560,14 +560,14 @@ impl< pub struct ViewSyncVoteAccumulator< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > { /// Map of all pre_commit signatures accumlated so far - pub pre_commit_vote_outcomes: VoteMap, + pub pre_commit_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// Map of all ommit signatures accumlated so far - pub commit_vote_outcomes: VoteMap, + pub commit_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// Map of all finalize signatures accumlated so far - pub finalize_vote_outcomes: VoteMap, + pub finalize_vote_outcomes: VoteMap, TYPES::VoteTokenType>, /// A quorum's worth of stake, generally 2f + 1 pub success_threshold: NonZeroU64, @@ -584,7 +584,7 @@ pub struct ViewSyncVoteAccumulator< impl< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > Accumulator2 for ViewSyncVoteAccumulator { #[allow(clippy::too_many_lines)] @@ -734,7 +734,7 @@ impl< pub struct AccumulatorPlaceholder< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > { /// Phantom data to make compiler happy pub phantom: PhantomData<(TYPES, VOTE, COMMITTABLE)>, @@ -743,7 +743,7 @@ pub struct AccumulatorPlaceholder< impl< TYPES: NodeType, COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType, + VOTE: VoteType>, > Accumulator2 for AccumulatorPlaceholder { fn append( @@ -758,17 +758,23 @@ impl< /// Mapping of commitments to vote tokens by key. // TODO ED Remove this whole token generic -type VoteMap = HashMap< - Commitment, +type VoteMap = HashMap< + COMMITMENT, ( u64, - BTreeMap>, TOKEN)>, + BTreeMap, TOKEN)>, ), >; /// Describe the process of collecting signatures on block or leaf commitment, to form a DAC or QC, /// respectively. -pub struct VoteAccumulator { +/// +/// TODO GG used only in election.rs; move this to there and make it private? +pub struct VoteAccumulator< + TOKEN, + COMMITMENT: Serialize + for<'a> Deserialize<'a> + Clone, + TYPES: NodeType, +> { /// Map of all signatures accumlated so far pub total_vote_outcomes: VoteMap, /// Map of all da signatures accumlated so far @@ -809,7 +815,7 @@ impl ), ), AssembledSignature, - > for VoteAccumulator + > for VoteAccumulator, TYPES> where TOKEN: Clone + VoteToken, { From 6f85c106ef7a2c8789c4fe14bc869ed8ab102add Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Thu, 21 Sep 2023 13:45:05 -0400 Subject: [PATCH 05/37] chore: Remove Committable from more types (#1792) * remove Committable from Accumulator2 * remove Committable from AccumulatorPlaceholder * remove Committable from DAVoteAccumulator type param * remove Committable from QuorumVoteAccumulator type param * remove Committable from ViewSyncVoteAccumulator type param * remove Committable from SignedCertificate type param (that's a big one) --- crates/task-impls/src/consensus.rs | 4 +- crates/task-impls/src/da.rs | 4 +- crates/task-impls/src/view_sync.rs | 4 +- crates/types/src/certificate.rs | 14 ++++--- crates/types/src/traits/election.rs | 20 +++++----- crates/types/src/vote.rs | 61 +++++++++++++++-------------- 6 files changed, 55 insertions(+), 52 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index dccf7919c3..ef4694a282 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -4,7 +4,7 @@ use async_lock::{RwLock, RwLockUpgradableReadGuard}; #[cfg(async_executor_impl = "async-std")] use async_std::task::JoinHandle; use bitvec::prelude::*; -use commit::Committable; +use commit::{Commitment, Committable}; use core::time::Duration; use either::{Either, Left, Right}; use futures::FutureExt; @@ -151,7 +151,7 @@ pub struct VoteCollectionTaskState< TYPES, TYPES::Time, TYPES::VoteTokenType, - SequencingLeaf, + Commitment>, >>::VoteAccumulator, QuorumCertificate>, >, diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index ff048ef469..9b1657324f 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -3,7 +3,7 @@ use async_compatibility_layer::art::async_spawn; use async_lock::RwLock; use bitvec::prelude::*; -use commit::Committable; +use commit::{Commitment, Committable}; use either::{Either, Left, Right}; use futures::FutureExt; use hotshot_task::{ @@ -103,7 +103,7 @@ pub struct DAVoteCollectionTaskState< TYPES, TYPES::Time, TYPES::VoteTokenType, - TYPES::BlockType, + Commitment, >>::VoteAccumulator, DACertificate, >, diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index f92752f487..eaac060975 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -1,7 +1,7 @@ #![allow(clippy::module_name_repetitions)] use crate::events::SequencingHotShotEvent; use async_compatibility_layer::art::{async_sleep, async_spawn}; -use commit::Committable; +use commit::{Commitment, Committable}; use either::Either::{self, Left, Right}; use futures::FutureExt; use hotshot_task::{ @@ -228,7 +228,7 @@ pub struct ViewSyncRelayTaskState< TYPES, TYPES::Time, TYPES::VoteTokenType, - ViewSyncData, + Commitment>, >>::VoteAccumulator, ViewSyncCertificate, >, diff --git a/crates/types/src/certificate.rs b/crates/types/src/certificate.rs index 5309729eb7..7018490e09 100644 --- a/crates/types/src/certificate.rs +++ b/crates/types/src/certificate.rs @@ -157,11 +157,11 @@ pub struct VoteMetaData> - SignedCertificate + SignedCertificate> for QuorumCertificate { type Vote = QuorumVote; - type VoteAccumulator = QuorumVoteAccumulator; + type VoteAccumulator = QuorumVoteAccumulator, Self::Vote>; fn from_signatures_and_commitment( signatures: AssembledSignature, @@ -234,11 +234,12 @@ impl> Committable } } -impl SignedCertificate +impl + SignedCertificate> for DACertificate { type Vote = DAVote; - type VoteAccumulator = DAVoteAccumulator; + type VoteAccumulator = DAVoteAccumulator, Self::Vote>; fn from_signatures_and_commitment( signatures: AssembledSignature, @@ -323,11 +324,12 @@ impl Committable for ViewSyncCertificate { } impl - SignedCertificate> + SignedCertificate>> for ViewSyncCertificate { type Vote = ViewSyncVote; - type VoteAccumulator = ViewSyncVoteAccumulator, Self::Vote>; + type VoteAccumulator = + ViewSyncVoteAccumulator>, Self::Vote>; /// Build a QC from the threshold signature and commitment fn from_signatures_and_commitment( signatures: AssembledSignature, diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index fb1ff72a58..7ccde773af 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -158,17 +158,17 @@ pub trait ElectionConfig: } /// A certificate of some property which has been signed by a quroum of nodes. -pub trait SignedCertificate +pub trait SignedCertificate where Self: Send + Sync + Clone + Serialize + for<'a> Deserialize<'a>, - COMMITTABLE: Committable + Serialize + Clone, + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, TOKEN: VoteToken, { /// `VoteType` that is used in this certificate - type Vote: VoteType>; + type Vote: VoteType; /// `Accumulator` type to accumulate votes. - type VoteAccumulator: Accumulator2; + type VoteAccumulator: Accumulator2; /// Build a QC from the threshold signature and commitment // TODO ED Rename this function and rework this function parameters @@ -189,10 +189,10 @@ where // TODO ED Make an issue for this /// Get the leaf commitment. - fn leaf_commitment(&self) -> Commitment; + fn leaf_commitment(&self) -> COMMITMENT; /// Set the leaf commitment. - fn set_leaf_commitment(&mut self, commitment: Commitment); + fn set_leaf_commitment(&mut self, commitment: COMMITMENT); /// Get whether the certificate is for the genesis block. fn is_genesis(&self) -> bool; @@ -269,7 +269,7 @@ pub trait ConsensusExchange: Send + Sync { // TODO ED Make this equal Certificate vote (if possible?) type Vote: VoteType>; /// A [`SignedCertificate`] attesting to a decision taken by the committee. - type Certificate: SignedCertificate + type Certificate: SignedCertificate> + Hash + Eq; /// The committee eligible to make decisions. @@ -468,13 +468,13 @@ pub trait ConsensusExchange: Send + Sync { TYPES, TYPES::Time, TYPES::VoteTokenType, - Self::Commitment, + Commitment, >>::VoteAccumulator, vote: &<>::Certificate as SignedCertificate< TYPES, TYPES::Time, TYPES::VoteTokenType, - Self::Commitment, + Commitment, >>::Vote, _commit: &Commitment, ) -> Either< @@ -482,7 +482,7 @@ pub trait ConsensusExchange: Send + Sync { TYPES, TYPES::Time, TYPES::VoteTokenType, - Self::Commitment, + Commitment, >>::VoteAccumulator, Self::Certificate, > { diff --git a/crates/types/src/vote.rs b/crates/types/src/vote.rs index c470925b54..c27225e4af 100644 --- a/crates/types/src/vote.rs +++ b/crates/types/src/vote.rs @@ -22,6 +22,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, HashMap}, fmt::Debug, + hash::Hash, marker::PhantomData, num::NonZeroU64, }; @@ -319,8 +320,8 @@ pub trait Accumulator: Sized { /// Accumulator trait used to accumulate votes into an `AssembledSignature` pub trait Accumulator2< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + VOTE: VoteType, >: Sized { /// Append 1 vote to the accumulator. If the threshold is not reached, return @@ -337,11 +338,11 @@ pub trait Accumulator2< /// Accumulates DA votes pub struct DAVoteAccumulator< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + VOTE: VoteType, > { /// Map of all da signatures accumlated so far - pub da_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub da_vote_outcomes: VoteMap, /// A quorum's worth of stake, generally 2f + 1 pub success_threshold: NonZeroU64, /// A list of valid signatures for certificate aggregation @@ -354,9 +355,9 @@ pub struct DAVoteAccumulator< impl< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, - > Accumulator2 for DAVoteAccumulator + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone + Copy + PartialEq + Eq + Hash, + VOTE: VoteType, + > Accumulator2 for DAVoteAccumulator { fn append( mut self, @@ -428,15 +429,15 @@ impl< /// Accumulate quorum votes pub struct QuorumVoteAccumulator< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + VOTE: VoteType, > { /// Map of all signatures accumlated so far - pub total_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub total_vote_outcomes: VoteMap, /// Map of all yes signatures accumlated so far - pub yes_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub yes_vote_outcomes: VoteMap, /// Map of all no signatures accumlated so far - pub no_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub no_vote_outcomes: VoteMap, /// A quorum's worth of stake, generally 2f + 1 pub success_threshold: NonZeroU64, @@ -452,9 +453,9 @@ pub struct QuorumVoteAccumulator< impl< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, - > Accumulator2 for QuorumVoteAccumulator + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone + Copy + PartialEq + Eq + Hash, + VOTE: VoteType, + > Accumulator2 for QuorumVoteAccumulator { fn append( mut self, @@ -559,15 +560,15 @@ impl< /// Accumulates view sync votes pub struct ViewSyncVoteAccumulator< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + VOTE: VoteType, > { /// Map of all pre_commit signatures accumlated so far - pub pre_commit_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub pre_commit_vote_outcomes: VoteMap, /// Map of all ommit signatures accumlated so far - pub commit_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub commit_vote_outcomes: VoteMap, /// Map of all finalize signatures accumlated so far - pub finalize_vote_outcomes: VoteMap, TYPES::VoteTokenType>, + pub finalize_vote_outcomes: VoteMap, /// A quorum's worth of stake, generally 2f + 1 pub success_threshold: NonZeroU64, @@ -583,9 +584,9 @@ pub struct ViewSyncVoteAccumulator< impl< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, - > Accumulator2 for ViewSyncVoteAccumulator + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone + Copy + PartialEq + Eq + Hash, + VOTE: VoteType, + > Accumulator2 for ViewSyncVoteAccumulator { #[allow(clippy::too_many_lines)] fn append( @@ -733,18 +734,18 @@ impl< /// Placeholder accumulator; will be replaced by accumulator for each certificate type pub struct AccumulatorPlaceholder< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + VOTE: VoteType, > { /// Phantom data to make compiler happy - pub phantom: PhantomData<(TYPES, VOTE, COMMITTABLE)>, + pub phantom: PhantomData<(TYPES, VOTE, COMMITMENT)>, } impl< TYPES: NodeType, - COMMITTABLE: Committable + Serialize + Clone, - VOTE: VoteType>, - > Accumulator2 for AccumulatorPlaceholder + COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + VOTE: VoteType, + > Accumulator2 for AccumulatorPlaceholder { fn append( self, From 34216bce323479b950030af90c6886dc7ea17c67 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Thu, 21 Sep 2023 17:31:09 -0700 Subject: [PATCH 06/37] Save before sync with main --- Cargo.lock | 2 +- crates/hotshot/Cargo.toml | 1 - crates/hotshot/examples/infra/modDA.rs | 9 +-- crates/hotshot/src/demo.rs | 10 +-- crates/hotshot/src/lib.rs | 4 +- crates/hotshot/src/tasks/mod.rs | 6 +- crates/task-impls/src/consensus.rs | 17 +++-- crates/task-impls/src/da.rs | 35 +--------- crates/task-impls/src/transactions.rs | 76 ++++++++++++++++++--- crates/testing/src/node_types.rs | 6 +- crates/testing/src/task_helpers.rs | 12 ++-- crates/testing/tests/atomic_storage.rs | 70 ------------------- crates/testing/tests/da_task.rs | 28 ++++---- crates/testing/tests/network_task.rs | 22 +++--- crates/types/Cargo.toml | 1 + crates/{hotshot => types}/src/block_impl.rs | 73 +++++++++++++------- crates/types/src/data.rs | 2 - crates/types/src/lib.rs | 1 + crates/types/src/traits/block_contents.rs | 35 ++-------- crates/types/src/traits/state.rs | 12 ---- 20 files changed, 185 insertions(+), 237 deletions(-) rename crates/{hotshot => types}/src/block_impl.rs (57%) diff --git a/Cargo.lock b/Cargo.lock index 30f9f438b1..1f0a2bb9f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2609,7 +2609,6 @@ dependencies = [ "rand_chacha 0.3.1", "serde", "serde_json", - "sha3", "snafu", "surf-disco", "time 0.3.28", @@ -2833,6 +2832,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.7", + "sha3", "snafu", "tagged-base64 0.2.4", "time 0.3.28", diff --git a/crates/hotshot/Cargo.toml b/crates/hotshot/Cargo.toml index 671519ec84..d7816208f1 100644 --- a/crates/hotshot/Cargo.toml +++ b/crates/hotshot/Cargo.toml @@ -108,7 +108,6 @@ libp2p-networking = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } serde = { workspace = true, features = ["rc"] } -sha3 = "^0.10" snafu = { workspace = true } surf-disco = { workspace = true } time = { workspace = true } diff --git a/crates/hotshot/examples/infra/modDA.rs b/crates/hotshot/examples/infra/modDA.rs index ae0f0e40f5..82cc12bf68 100644 --- a/crates/hotshot/examples/infra/modDA.rs +++ b/crates/hotshot/examples/infra/modDA.rs @@ -20,8 +20,8 @@ use hotshot_orchestrator::{ config::{NetworkConfig, WebServerConfig}, }; use hotshot_task::task::FilterEvent; -use hotshot_types::HotShotConfig; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::ViewSyncCertificate, data::{QuorumProposal, SequencingLeaf, TestableLeaf}, event::{Event, EventType}, @@ -37,6 +37,7 @@ use hotshot_types::{ }, state::{ConsensusTime, TestableBlock, TestableState}, }, + HotShotConfig, }; use libp2p_identity::{ ed25519::{self, SecretKey}, @@ -407,7 +408,7 @@ pub struct WebServerDARun< #[async_trait] impl< - TYPES: NodeType, + TYPES: NodeType, MEMBERSHIP: Membership + Debug, NODE: NodeImplementation< TYPES, @@ -551,7 +552,7 @@ pub struct Libp2pDARun, MEMBERSHIP #[async_trait] impl< - TYPES: NodeType, + TYPES: NodeType, MEMBERSHIP: Membership + Debug, NODE: NodeImplementation< TYPES, @@ -765,7 +766,7 @@ where /// Main entry point for validators pub async fn main_entry_point< - TYPES: NodeType, + TYPES: NodeType, MEMBERSHIP: Membership + Debug, DANETWORK: CommunicationChannel, MEMBERSHIP> + Debug, QUORUMNETWORK: CommunicationChannel, MEMBERSHIP> + Debug, diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index feaed2fe6b..976cea433d 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -5,15 +5,13 @@ //! //! These implementations are useful in examples and integration testing, but are not suitable for //! production use. -use crate::{ - block_impl::{BlockPayloadError, VIDBlockPayload, VIDTransaction}, - traits::election::static_committee::{StaticElectionConfig, StaticVoteToken}, -}; +use crate::traits::election::static_committee::{StaticElectionConfig, StaticVoteToken}; use commit::{Commitment, Committable}; use derivative::Derivative; use either::Either; use hotshot_signature_key::bn254::BLSPubKey; use hotshot_types::{ + block_impl::{BlockPayloadError, VIDBlockPayload, VIDTransaction}, certificate::{AssembledSignature, QuorumCertificate}, data::{ fake_commitment, genesis_proposer_id, random_commitment, LeafType, SequencingLeaf, @@ -72,10 +70,6 @@ impl State for SDemoState { type Time = ViewNumber; - fn next_block(_state: Option) -> Self::BlockType { - VIDBlockPayload(Vec::new()) - } - fn validate_block(&self, _block: &Self::BlockType, view_number: &Self::Time) -> bool { if view_number == &ViewNumber::genesis() { &self.view_number == view_number diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index 117153967e..fe50fac759 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -19,7 +19,6 @@ #[cfg(feature = "docs")] pub mod documentation; -pub mod block_impl; /// Contains structures and functions for committee election pub mod certificate; #[cfg(feature = "demo")] @@ -56,6 +55,7 @@ use hotshot_task::{ use hotshot_task_impls::{events::SequencingHotShotEvent, network::NetworkTaskKind}; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::{DACertificate, ViewSyncCertificate}, consensus::{BlockStore, Consensus, ConsensusMetrics, View, ViewInner, ViewQueue}, data::{DAProposal, DeltasType, LeafType, QuorumProposal, SequencingLeaf}, @@ -649,7 +649,7 @@ pub trait HotShotType> { #[async_trait] impl< - TYPES: NodeType, + TYPES: NodeType, I: NodeImplementation< TYPES, Leaf = SequencingLeaf, diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 619fdb6d59..02aed896af 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -27,6 +27,7 @@ use hotshot_task_impls::{ view_sync::{ViewSyncTaskState, ViewSyncTaskStateTypes}, }; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::ViewSyncCertificate, data::{ProposalType, QuorumProposal, SequencingLeaf}, event::Event, @@ -38,7 +39,6 @@ use hotshot_types::{ CommitteeEx, ExchangesType, NodeImplementation, NodeType, ViewSyncEx, }, state::ConsensusTime, - BlockPayload, }, vote::{ViewSyncData, VoteType}, }; @@ -284,7 +284,7 @@ where consensus, timeout: handle.hotshot.inner.config.next_view_timeout, cur_view: TYPES::Time::new(0), - block: TYPES::BlockType::new(), + block: None, quorum_exchange: c_api.inner.exchanges.quorum_exchange().clone().into(), api: c_api.clone(), committee_exchange: c_api.inner.exchanges.committee_exchange().clone().into(), @@ -412,7 +412,7 @@ where /// # Panics /// Is unable to panic. This section here is just to satisfy clippy pub async fn add_transaction_task< - TYPES: NodeType, + TYPES: NodeType, I: NodeImplementation< TYPES, Leaf = SequencingLeaf, diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index dccf7919c3..7aa93de10e 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -83,8 +83,8 @@ pub struct SequencingConsensusTaskState< /// View number this view is executing in. pub cur_view: TYPES::Time, - /// Current block submitted to DA - pub block: TYPES::BlockType, + /// Current block submitted to DA, if any. + pub block: Option, /// the quorum exchange pub quorum_exchange: Arc>, @@ -1078,7 +1078,7 @@ where } SequencingHotShotEvent::SendDABlockData(block) => { // ED TODO Should make sure this is actually the most recent block - self.block = block; + self.block = Some(block); } _ => {} } @@ -1150,10 +1150,13 @@ where // TODO do some sort of sanity check on the view number that it matches decided } - let block_commitment = self.block.commit(); - if block_commitment == TYPES::BlockType::new().commit() { - debug!("BlockPayload is generic block! {:?}", self.cur_view); - } + let block_commitment = match &self.block { + Some(block) => block.commit(), + None => { + debug!("No block yet."); + return false; + } + }; let leaf = SequencingLeaf { view_number: view, diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index ff048ef469..61b95267a7 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -18,7 +18,7 @@ use hotshot_types::vote::VoteType; use hotshot_types::{ certificate::DACertificate, consensus::{Consensus, View}, - data::{DAProposal, ProposalType, SequencingLeaf, VidDisperse, VidScheme, VidSchemeTrait}, + data::{DAProposal, ProposalType, SequencingLeaf}, message::{Message, Proposal, SequencingMessage}, traits::{ consensus_api::SequencingConsensusApi, @@ -658,39 +658,6 @@ where self.committee_exchange.public_key().clone(), )) .await; - - debug!("Prepare VID shares"); - { - /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 - const NUM_STORAGE_NODES: usize = 10; - /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 - const NUM_CHUNKS: usize = 5; - - // TODO https://github.com/EspressoSystems/HotShot/issues/1686 - let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); - - let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); - let message_bytes = bincode::serialize(&message).unwrap(); - let vid_disperse = vid.disperse(&message_bytes).unwrap(); - // TODO for now reuse the same block commitment and signature as DA committee - // https://github.com/EspressoSystems/jellyfish/issues/369 - - self.event_stream - .publish(SequencingHotShotEvent::VidDisperseSend( - Proposal { - data: VidDisperse { - view_number: view, - commitment: block.commit(), // TODO GG should be vid_disperse.commit but that's a big change - shares: vid_disperse.shares, - common: vid_disperse.common, - }, - signature: message.signature, - }, - // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 - self.committee_exchange.public_key().clone(), - )) - .await; - } } SequencingHotShotEvent::Timeout(view) => { diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 8609708653..ff832a272c 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -13,15 +13,17 @@ use hotshot_task::{ task_impls::HSTWithEvent, }; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::DACertificate, consensus::Consensus, - data::SequencingLeaf, + data::{SequencingLeaf, VidScheme, VidSchemeTrait}, message::{Message, SequencingMessage}, traits::{ + block_contents::Transaction, consensus_api::SequencingConsensusApi, election::ConsensusExchange, node_implementation::{CommitteeEx, NodeImplementation, NodeType}, - BlockPayload, State, + BlockPayload, }, }; use hotshot_utils::bincode::bincode_opts; @@ -72,7 +74,7 @@ pub struct TransactionTaskState< } impl< - TYPES: NodeType, + TYPES: NodeType, I: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -220,18 +222,52 @@ where drop(consensus); - let mut block = ::StateType::next_block(None); + let block; let txns = self.wait_for_transactions(parent_leaf).await?; - for txn in txns { - if let Ok(new_block) = block.add_transaction_raw(&txn) { - block = new_block; - continue; + debug!("Prepare VID shares"); + if txns.len() > 0 { + /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 + const NUM_STORAGE_NODES: usize = 10; + /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 + const NUM_CHUNKS: usize = 5; + + // TODO https://github.com/EspressoSystems/HotShot/issues/1686 + let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); + + let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + // TODO https://github.com/EspressoSystems/jellyfish/issues/375 + let mut txns_flatten = Vec::new(); + for txn in &txns { + txns_flatten.extend(txn.bytes()); } + tracing::error!("here txn task {:?}", txns); + let vid_disperse = vid.disperse(&txns_flatten).unwrap(); + block = VIDBlockPayload::new(txns, vid_disperse.commit); + + // TODO Commenting out the following code since we need to update the proposal, + // signature, and exchange for VID dispersal. They were copy-pasted from DA + // code. + // self.event_stream + // .publish(SequencingHotShotEvent::VidDisperseSend( + // Proposal { + // data: VidDisperse { + // view_number: view + 1, + // commitment: block.commit(), + // shares: vid_disperse.shares, + // common: vid_disperse.common, + // }, + // signature: message.signature, + // }, + // // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 + // self.committee_exchange.public_key().clone(), + // )) + // .await; + + self.event_stream + .publish(SequencingHotShotEvent::BlockReady(block, view + 1)) + .await; } - self.event_stream - .publish(SequencingHotShotEvent::BlockReady(block, view + 1)) - .await; return None; } SequencingHotShotEvent::Shutdown => { @@ -241,7 +277,25 @@ where } None } +} +impl< + TYPES: NodeType, + I: NodeImplementation< + TYPES, + Leaf = SequencingLeaf, + ConsensusMessage = SequencingMessage, + >, + A: SequencingConsensusApi, I> + 'static, + > TransactionTaskState +where + CommitteeEx: ConsensusExchange< + TYPES, + Message, + Certificate = DACertificate, + Commitment = TYPES::BlockType, + >, +{ #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Transaction Handling Task", level = "error")] async fn wait_for_transactions( &self, diff --git a/crates/testing/src/node_types.rs b/crates/testing/src/node_types.rs index f4b2f9db1a..4ffd74e2bf 100644 --- a/crates/testing/src/node_types.rs +++ b/crates/testing/src/node_types.rs @@ -1,7 +1,4 @@ -use hotshot::{ - block_impl::{VIDBlockPayload, VIDTransaction}, - traits::implementations::CombinedNetworks, -}; +use hotshot::traits::implementations::CombinedNetworks; use std::{marker::PhantomData, sync::Arc}; use hotshot::{ @@ -17,6 +14,7 @@ use hotshot::{ types::bn254::BLSPubKey, }; use hotshot_types::{ + block_impl::{VIDBlockPayload, VIDTransaction}, certificate::ViewSyncCertificate, data::{QuorumProposal, SequencingLeaf, ViewNumber}, message::{Message, SequencingMessage}, diff --git a/crates/testing/src/task_helpers.rs b/crates/testing/src/task_helpers.rs index 8e0f85a95c..1a8123a35b 100644 --- a/crates/testing/src/task_helpers.rs +++ b/crates/testing/src/task_helpers.rs @@ -6,13 +6,14 @@ use commit::Committable; use either::Right; use hotshot::{ certificate::QuorumCertificate, - traits::{BlockPayload, NodeImplementation, TestableNodeImplementation}, + traits::{NodeImplementation, TestableNodeImplementation}, types::{bn254::BLSPubKey, SignatureKey, SystemContextHandle}, HotShotInitializer, HotShotSequencingConsensusApi, SystemContext, }; use hotshot_task::event_stream::ChannelStream; use hotshot_task_impls::events::SequencingHotShotEvent; use hotshot_types::{ + block_impl::VIDBlockPayload, data::{QuorumProposal, SequencingLeaf, VidScheme, ViewNumber}, message::{Message, Proposal}, traits::{ @@ -21,7 +22,7 @@ use hotshot_types::{ metrics::NoMetrics, node_implementation::{CommitteeEx, ExchangesType, NodeType, QuorumEx}, signature_key::EncodedSignature, - state::ConsensusTime, + state::{ConsensusTime, TestableBlock}, }, }; @@ -116,8 +117,7 @@ async fn build_quorum_proposal_and_signature( let parent_leaf = leaf.clone(); // every event input is seen on the event stream in the output. - - let block_commitment = ::BlockType::new().commit(); + let block = ::genesis(); let leaf = SequencingLeaf { view_number: ViewNumber::new(view), height: parent_leaf.height + 1, @@ -125,14 +125,14 @@ async fn build_quorum_proposal_and_signature( parent_commitment: parent_leaf.commit(), // Use the block commitment rather than the block, so that the replica can construct // the same leaf with the commitment. - deltas: Right(block_commitment), + deltas: Right(block.commit()), rejected: vec![], timestamp: 0, proposer_id: api.public_key().to_bytes(), }; let signature = ::sign(private_key, leaf.commit().as_ref()); let proposal = QuorumProposal::> { - block_commitment, + block_commitment: block.commit(), view_number: ViewNumber::new(view), height: 1, justify_qc: QuorumCertificate::genesis(), diff --git a/crates/testing/tests/atomic_storage.rs b/crates/testing/tests/atomic_storage.rs index c8183af164..381db09d87 100644 --- a/crates/testing/tests/atomic_storage.rs +++ b/crates/testing/tests/atomic_storage.rs @@ -13,76 +13,6 @@ use rand::thread_rng; type AtomicStorage = hotshot::traits::implementations::AtomicStorage; -#[cfg_attr( - async_executor_impl = "tokio", - tokio::test(flavor = "multi_thread", worker_threads = 2) -)] -#[cfg_attr(async_executor_impl = "async-std", async_std::test)] -async fn test_happy_path_blocks() { - // This folder will be destroyed when the last handle to it closes - let file = tempfile::tempdir().expect("Could not create temp dir"); - let path = file.path(); - println!("Using store in {:?}", path); - let mut store = AtomicStorage::open(path).expect("Could not open atomic store"); - - let block = VDEntryBlock::default(); - let hash = block.hash(); - store - .update(|mut m| { - let block = block.clone(); - async move { m.insert_block(hash, block).await } - }) - .await - .unwrap(); - - // Make sure the data is still there after re-opening - drop(store); - store = AtomicStorage::open(path).expect("Could not open atomic store"); - assert_eq!( - store.get_block(&hash).await.unwrap(), - Some(DEntryBlock::default()) - ); - - // Add some transactions - let mut rng = thread_rng(); - let state = >::get_starting_state(); - let mut hashes = Vec::new(); - let mut block = block; - for _ in 0..10 { - let new = block - .add_transaction_raw(&random_transaction(&state, &mut rng)) - .expect("Could not add transaction"); - println!("Inserting {:?}: {:?}", new.hash(), new); - store - .update(|mut m| { - let new = new.clone(); - async move { m.insert_block(new.hash(), new.clone()).await } - }) - .await - .unwrap(); - hashes.push(new.hash()); - block = new; - } - - // read them all back 3 times - // 1st time: normal readback - // 2nd: after dropping and re-opening the store - for i in 0..3 { - if i == 1 { - drop(store); - store = AtomicStorage::open(path).expect("Could not open atomic store"); - } - - // read them all back - for (idx, hash) in hashes.iter().enumerate() { - match store.get_block(hash).await.expect("Could not read hash") { - Some(block) => println!("read {:?}", block), - None => panic!("Could not read hash {} {:?}", idx, hash), - } - } - } -} - #[cfg_attr( async_executor_impl = "tokio", tokio::test(flavor = "multi_thread", worker_threads = 2) diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index 204038885c..ba042b35ee 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -6,6 +6,7 @@ use hotshot_testing::{ task_helpers::vid_init, }; use hotshot_types::{ + block_impl::VIDTransaction, data::{DAProposal, VidDisperse, VidSchemeTrait, ViewNumber}, traits::{ consensus_api::ConsensusSharedApi, election::ConsensusExchange, @@ -20,10 +21,12 @@ use std::collections::HashMap; )] #[cfg_attr(async_executor_impl = "async-std", async_std::test)] async fn test_da_task() { - use hotshot::{block_impl::VIDBlockPayload, tasks::add_da_task}; + use hotshot::tasks::add_da_task; use hotshot_task_impls::harness::run_harness; use hotshot_testing::task_helpers::build_system_handle; - use hotshot_types::{message::Proposal, traits::election::CommitteeExchangeType}; + use hotshot_types::{ + block_impl::VIDBlockPayload, message::Proposal, traits::election::CommitteeExchangeType, + }; async_compatibility_layer::logging::setup_logging(); async_compatibility_layer::logging::setup_backtrace(); @@ -36,9 +39,13 @@ async fn test_da_task() { }; let committee_exchange = api.inner.exchanges.committee_exchange().clone(); let pub_key = *api.public_key(); - let block = VIDBlockPayload(Vec::new()); - let block_commitment = block.commit(); - let signature = committee_exchange.sign_da_proposal(&block_commitment); + let vid = vid_init(); + let txn = vec![0u8]; + tracing::error!("here da task"); + let vid_disperse = vid.disperse(&txn).unwrap(); + let block_commitment = vid_disperse.commit; + let block = VIDBlockPayload::new(vec![VIDTransaction(txn)], block_commitment); + let signature = committee_exchange.sign_da_proposal(&block.commit()); let proposal = DAProposal { deltas: block.clone(), view_number: ViewNumber::new(2), @@ -47,13 +54,10 @@ async fn test_da_task() { data: proposal, signature, }; - let vid = vid_init(); - let message_bytes = bincode::serialize(&message).unwrap(); - let vid_disperse = vid.disperse(&message_bytes).unwrap(); let vid_proposal = Proposal { data: VidDisperse { view_number: message.data.view_number, - commitment: block_commitment, + commitment: block.commit(), shares: vid_disperse.shares, common: vid_disperse.common, }, @@ -88,7 +92,7 @@ async fn test_da_task() { SequencingHotShotEvent::BlockReady(block.clone(), ViewNumber::new(2)), 1, ); - output.insert(SequencingHotShotEvent::SendDABlockData(block), 1); + output.insert(SequencingHotShotEvent::SendDABlockData(block.clone()), 1); output.insert( SequencingHotShotEvent::DAProposalSend(message.clone(), pub_key), 1, @@ -98,7 +102,7 @@ async fn test_da_task() { .unwrap() .unwrap(); let da_vote = - committee_exchange.create_da_message(block_commitment, ViewNumber::new(2), vote_token); + committee_exchange.create_da_message(block.commit(), ViewNumber::new(2), vote_token); output.insert(SequencingHotShotEvent::DAVoteSend(da_vote), 1); output.insert( SequencingHotShotEvent::VidDisperseSend(vid_proposal.clone(), pub_key), @@ -110,7 +114,7 @@ async fn test_da_task() { .unwrap() .unwrap(); let vid_vote = - committee_exchange.create_vid_message(block_commitment, ViewNumber::new(2), vote_token); + committee_exchange.create_vid_message(block.commit(), ViewNumber::new(2), vote_token); output.insert(SequencingHotShotEvent::VidVoteSend(vid_vote), 1); output.insert(SequencingHotShotEvent::DAProposalRecv(message, pub_key), 1); diff --git a/crates/testing/tests/network_task.rs b/crates/testing/tests/network_task.rs index 7ad17e2008..f11508e8f6 100644 --- a/crates/testing/tests/network_task.rs +++ b/crates/testing/tests/network_task.rs @@ -21,11 +21,13 @@ use std::collections::HashMap; #[cfg_attr(async_executor_impl = "async-std", async_std::test)] #[ignore] async fn test_network_task() { - use hotshot::block_impl::VIDBlockPayload; use hotshot_task_impls::harness::run_harness; use hotshot_testing::task_helpers::build_system_handle; use hotshot_types::{ - data::VidDisperse, message::Proposal, traits::election::CommitteeExchangeType, + block_impl::{VIDBlockPayload, VIDTransaction}, + data::VidDisperse, + message::Proposal, + traits::election::CommitteeExchangeType, }; async_compatibility_layer::logging::setup_logging(); @@ -40,9 +42,13 @@ async fn test_network_task() { let committee_exchange = api.inner.exchanges.committee_exchange().clone(); let pub_key = *api.public_key(); let priv_key = api.private_key(); - let block = VIDBlockPayload(Vec::new()); - let block_commitment = block.commit(); - let signature = committee_exchange.sign_da_proposal(&block_commitment); + let vid = vid_init(); + let txn = vec![0u8]; + tracing::error!("here network task1"); + let vid_disperse = vid.disperse(&txn).unwrap(); + let block_commitment = vid_disperse.commit; + let block = VIDBlockPayload::new(vec![VIDTransaction(txn)], block_commitment); + let signature = committee_exchange.sign_da_proposal(&block.commit()); let da_proposal = Proposal { data: DAProposal { deltas: block.clone(), @@ -51,15 +57,13 @@ async fn test_network_task() { signature, }; let quorum_proposal = build_quorum_proposal(&handle, priv_key, 2).await; - let vid = vid_init(); - let da_proposal_bytes = bincode::serialize(&da_proposal).unwrap(); - let vid_disperse = vid.disperse(&da_proposal_bytes).unwrap(); // TODO for now reuse the same block commitment and signature as DA committee // https://github.com/EspressoSystems/jellyfish/issues/369 + tracing::error!("here network task2"); let da_vid_disperse = Proposal { data: VidDisperse { view_number: da_proposal.data.view_number, - commitment: block_commitment, + commitment: block.commit(), shares: vid_disperse.shares, common: vid_disperse.common, }, diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 742882cce2..dbc1b7b009 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -43,6 +43,7 @@ rand = { workspace = true } rand_chacha = { workspace = true } serde = { workspace = true } sha2 = { workspace = true } +sha3 = "^0.10" snafu = { workspace = true } tagged-base64 = { git = "https://github.com/EspressoSystems/tagged-base64", tag = "0.2.4" } time = { workspace = true } diff --git a/crates/hotshot/src/block_impl.rs b/crates/types/src/block_impl.rs similarity index 57% rename from crates/hotshot/src/block_impl.rs rename to crates/types/src/block_impl.rs index 8960d79158..79b0ce234b 100644 --- a/crates/hotshot/src/block_impl.rs +++ b/crates/types/src/block_impl.rs @@ -4,8 +4,11 @@ use std::{ fmt::{Debug, Display}, }; +use crate::{ + data::{test_srs, VidScheme, VidSchemeTrait}, + traits::{block_contents::Transaction, state::TestableBlock, BlockPayload}, +}; use commit::{Commitment, Committable}; -use hotshot_types::traits::{block_contents::Transaction, state::TestableBlock, BlockPayload}; use serde::{Deserialize, Serialize}; use sha3::{Digest, Keccak256}; use snafu::Snafu; @@ -28,7 +31,11 @@ impl Committable for VIDTransaction { } } -impl Transaction for VIDTransaction {} +impl Transaction for VIDTransaction { + fn bytes(&self) -> Vec { + self.0.clone() + } +} impl VIDTransaction { /// create a new transaction @@ -55,14 +62,31 @@ pub enum BlockPayloadError { /// A [`BlockPayload`] that contains a list of `VIDTransaction`. #[derive(PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] -pub struct VIDBlockPayload(pub Vec); +pub struct VIDBlockPayload { + /// List of transactions. + pub transactions: Vec, + /// VID commitment. + pub commitment: ::Commit, +} + +impl VIDBlockPayload { + /// Constructor. + #[must_use] + pub fn new( + transactions: Vec, + commitment: ::Commit, + ) -> Self { + Self { + transactions, + commitment, + } + } +} impl Committable for VIDBlockPayload { fn commit(&self) -> Commitment { - // TODO: Use use VID block commitment. - // let builder = commit::RawCommitmentBuilder::new("BlockPayload Comm"); - builder.finalize() + builder.generic_byte_array(&self.commitment).finalize() } fn tag() -> String { @@ -72,17 +96,30 @@ impl Committable for VIDBlockPayload { impl Display for VIDBlockPayload { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "BlockPayload #txns={}", self.0.len()) + write!(f, "BlockPayload #txns={}", self.transactions.len()) } } impl TestableBlock for VIDBlockPayload { fn genesis() -> Self { - VIDBlockPayload(Vec::new()) + /// TODO + const NUM_STORAGE_NODES: usize = 10; + /// TODO + const NUM_CHUNKS: usize = 5; + + // TODO + let srs = test_srs(NUM_STORAGE_NODES); + + let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + + let txn = vec![0u8]; + tracing::error!("here genesis"); + let vid_disperse = vid.disperse(&txn).unwrap(); + VIDBlockPayload::new(vec![VIDTransaction(txn)], vid_disperse.commit) } fn txn_count(&self) -> u64 { - self.0.len() as u64 + self.transactions.len() as u64 } } @@ -91,20 +128,10 @@ impl BlockPayload for VIDBlockPayload { type Transaction = VIDTransaction; - fn new() -> Self { - ::genesis() - } - - fn add_transaction_raw( - &self, - tx: &Self::Transaction, - ) -> std::result::Result { - let mut new = self.0.clone(); - new.push(tx.clone()); - Ok(VIDBlockPayload(new)) - } - fn contained_transactions(&self) -> HashSet> { - self.0.iter().map(commit::Committable::commit).collect() + self.transactions + .iter() + .map(commit::Committable::commit) + .collect() } } diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 080355a195..ff63321431 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -173,8 +173,6 @@ pub struct VidDisperse { /// The view number for which this VID data is intended pub view_number: TYPES::Time, /// Block commitment - /// - /// TODO GG type should be `::Common` but that's a big change. pub commitment: Commitment, /// VID shares dispersed among storage nodes pub shares: Vec<::Share>, diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 6152689acf..54739106c3 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -11,6 +11,7 @@ use std::{num::NonZeroUsize, time::Duration}; +pub mod block_impl; pub mod certificate; pub mod consensus; pub mod data; diff --git a/crates/types/src/traits/block_contents.rs b/crates/types/src/traits/block_contents.rs index a365dd7144..4ba10f601c 100644 --- a/crates/types/src/traits/block_contents.rs +++ b/crates/types/src/traits/block_contents.rs @@ -20,8 +20,6 @@ use std::{ /// * Must have a predefined error type ([`BlockPayload::Error`]) /// * Must have a transaction type that can be compared for equality, serialized and serialized, /// sent between threads, and can have a hash produced of it -/// * Must be able to be produced incrementally by appending transactions -/// ([`add_transaction_raw`](BlockPayload::add_transaction_raw)) /// * Must be hashable pub trait BlockPayload: Serialize @@ -42,18 +40,6 @@ pub trait BlockPayload: /// The type of the transitions we are applying type Transaction: Transaction; - /// Construct an empty or genesis block. - fn new() -> Self; - - /// Attempts to add a transaction, returning an Error if it would result in a structurally - /// invalid block - /// - /// # Errors - /// - /// Should return an error if this transaction leads to an invalid block - fn add_transaction_raw(&self, tx: &Self::Transaction) - -> std::result::Result; - /// returns hashes of all the transactions in this block /// TODO make this ordered with a vec fn contained_transactions(&self) -> HashSet>; @@ -63,6 +49,8 @@ pub trait BlockPayload: pub trait Transaction: Clone + Serialize + DeserializeOwned + Debug + PartialEq + Eq + Sync + Send + Committable + Hash { + /// Get the transaction bytes. + fn bytes(&self) -> Vec; } /// Dummy implementation of `BlockPayload` for unit tests @@ -112,7 +100,11 @@ pub mod dummy { "DUMMY_TXN".to_string() } } - impl super::Transaction for DummyTransaction {} + impl super::Transaction for DummyTransaction { + fn bytes(&self) -> Vec { + Vec::new() + } + } impl std::error::Error for DummyError {} @@ -133,19 +125,6 @@ pub mod dummy { type Transaction = DummyTransaction; - fn new() -> Self { - Self { nonce: 0 } - } - - fn add_transaction_raw( - &self, - _tx: &Self::Transaction, - ) -> std::result::Result { - Ok(Self { - nonce: self.nonce + 1, - }) - } - fn contained_transactions(&self) -> HashSet> { HashSet::new() } diff --git a/crates/types/src/traits/state.rs b/crates/types/src/traits/state.rs index 93ff3e6603..bd8fe7d2ed 100644 --- a/crates/types/src/traits/state.rs +++ b/crates/types/src/traits/state.rs @@ -20,8 +20,6 @@ use std::{ /// This trait represents the behaviors that the 'global' ledger state must have: /// * A defined error type ([`Error`](State::Error)) /// * The type of block that modifies this type of state ([`BlockPayload`](State::BlockType)) -/// * A method to get a template (empty) next block from the current state -/// ([`next_block`](State::next_block)) /// * The ability to validate that a block is actually a valid extension of this state /// ([`validate_block`](State::validate_block)) /// * The ability to produce a new state, with the modifications from the block applied @@ -46,9 +44,6 @@ pub trait State: /// Time compatibility needed for reward collection type Time: ConsensusTime; - /// Returns an empty, template next block given this current state - fn next_block(prev_commitment: Option) -> Self::BlockType; - /// Returns true if and only if the provided block is valid and can extend this state fn validate_block(&self, block: &Self::BlockType, view_number: &Self::Time) -> bool; @@ -165,13 +160,6 @@ pub mod dummy { type BlockType = DummyBlock; type Time = ViewNumber; - fn next_block(state: Option) -> Self::BlockType { - match state { - Some(state) => DummyBlock { nonce: state.nonce }, - None => unimplemented!(), - } - } - fn validate_block(&self, _block: &Self::BlockType, _view_number: &Self::Time) -> bool { false } From 36bdd80c596d37eb82c033d63a7d37b2a4700afd Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Thu, 21 Sep 2023 18:23:37 -0700 Subject: [PATCH 07/37] Fix empty block and txn --- crates/hotshot/src/demo.rs | 4 +-- crates/hotshot/src/tasks/mod.rs | 7 ++-- crates/task-impls/src/consensus.rs | 16 +++------ crates/task-impls/src/transactions.rs | 47 +++++++++++++-------------- crates/testing/tests/da_task.rs | 1 - crates/testing/tests/network_task.rs | 2 -- crates/types/src/block_impl.rs | 1 - 7 files changed, 34 insertions(+), 44 deletions(-) diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index 976cea433d..468ff5e420 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -101,9 +101,9 @@ impl TestableState for SDemoState { fn create_random_transaction( _state: Option<&Self>, _rng: &mut dyn rand::RngCore, - padding: u64, + _padding: u64, ) -> ::Transaction { - VIDTransaction(vec![0; padding as usize]) + VIDTransaction(vec![0]) } } /// Implementation of [`NodeType`] for [`VDemoNode`] diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 868768c3dc..bed3b3b344 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -38,7 +38,7 @@ use hotshot_types::{ node_implementation::{ CommitteeEx, ExchangesType, NodeImplementation, NodeType, ViewSyncEx, }, - state::ConsensusTime, + state::{ConsensusTime, TestableBlock}, }, vote::{ViewSyncData, VoteType}, }; @@ -251,7 +251,7 @@ where /// # Panics /// Is unable to panic. This section here is just to satisfy clippy pub async fn add_consensus_task< - TYPES: NodeType, + TYPES: NodeType, I: NodeImplementation< TYPES, Leaf = SequencingLeaf, @@ -289,7 +289,8 @@ where consensus, timeout: handle.hotshot.inner.config.next_view_timeout, cur_view: TYPES::Time::new(0), - block: None, + // TODO (Keyao) Shouldn't use test function. + block: ::genesis(), quorum_exchange: c_api.inner.exchanges.quorum_exchange().clone().into(), api: c_api.clone(), committee_exchange: c_api.inner.exchanges.committee_exchange().clone().into(), diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index ba5d288a23..b9a10e3d6e 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -80,11 +80,11 @@ pub struct SequencingConsensusTaskState< pub consensus: Arc>>>, /// View timeout from config. pub timeout: u64, - /// View number this view is executing in. + /// View number this view is executing in pub cur_view: TYPES::Time, - /// Current block submitted to DA, if any. - pub block: Option, + /// Current block submitted to DA + pub block: TYPES::BlockType, /// the quorum exchange pub quorum_exchange: Arc>, @@ -1078,7 +1078,7 @@ where } SequencingHotShotEvent::SendDABlockData(block) => { // ED TODO Should make sure this is actually the most recent block - self.block = Some(block); + self.block = block; } _ => {} } @@ -1150,13 +1150,7 @@ where // TODO do some sort of sanity check on the view number that it matches decided } - let block_commitment = match &self.block { - Some(block) => block.commit(), - None => { - debug!("No block yet."); - return false; - } - }; + let block_commitment = self.block.commit(); let leaf = SequencingLeaf { view_number: view, diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 2dce3684ba..c01cf1ca2b 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -18,12 +18,12 @@ use hotshot_types::{ block_impl::{VIDBlockPayload, VIDTransaction}, certificate::DACertificate, consensus::Consensus, - data::{SequencingLeaf, VidScheme, VidSchemeTrait}, - message::{Message, SequencingMessage}, + data::{SequencingLeaf, VidDisperse, VidScheme, VidSchemeTrait}, + message::{Message, Proposal, SequencingMessage}, traits::{ block_contents::Transaction, consensus_api::SequencingConsensusApi, - election::ConsensusExchange, + election::{CommitteeExchangeType, ConsensusExchange}, node_implementation::{CommitteeEx, NodeImplementation, NodeType}, BlockPayload, }, @@ -239,7 +239,7 @@ where let txns = self.wait_for_transactions(parent_leaf).await?; debug!("Prepare VID shares"); - if txns.len() > 0 { + if !txns.is_empty() { /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 const NUM_STORAGE_NODES: usize = 10; /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 @@ -254,31 +254,30 @@ where for txn in &txns { txns_flatten.extend(txn.bytes()); } - tracing::error!("here txn task {:?}", txns); let vid_disperse = vid.disperse(&txns_flatten).unwrap(); block = VIDBlockPayload::new(txns, vid_disperse.commit); - // TODO Commenting out the following code since we need to update the proposal, - // signature, and exchange for VID dispersal. They were copy-pasted from DA - // code. - // self.event_stream - // .publish(SequencingHotShotEvent::VidDisperseSend( - // Proposal { - // data: VidDisperse { - // view_number: view + 1, - // commitment: block.commit(), - // shares: vid_disperse.shares, - // common: vid_disperse.common, - // }, - // signature: message.signature, - // }, - // // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 - // self.committee_exchange.public_key().clone(), - // )) - // .await; + self.event_stream + .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) + .await; self.event_stream - .publish(SequencingHotShotEvent::BlockReady(block, view + 1)) + .publish(SequencingHotShotEvent::VidDisperseSend( + Proposal { + data: VidDisperse { + view_number: view + 1, + commitment: block.commit(), + shares: vid_disperse.shares, + common: vid_disperse.common, + }, + // TODO (Keyao) This is also signed in DA task. + signature: self + .committee_exchange + .sign_da_proposal(&block.commit()), + }, + // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 + self.committee_exchange.public_key().clone(), + )) .await; } return None; diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index ba042b35ee..7c8b389d95 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -41,7 +41,6 @@ async fn test_da_task() { let pub_key = *api.public_key(); let vid = vid_init(); let txn = vec![0u8]; - tracing::error!("here da task"); let vid_disperse = vid.disperse(&txn).unwrap(); let block_commitment = vid_disperse.commit; let block = VIDBlockPayload::new(vec![VIDTransaction(txn)], block_commitment); diff --git a/crates/testing/tests/network_task.rs b/crates/testing/tests/network_task.rs index f11508e8f6..3413bc4898 100644 --- a/crates/testing/tests/network_task.rs +++ b/crates/testing/tests/network_task.rs @@ -44,7 +44,6 @@ async fn test_network_task() { let priv_key = api.private_key(); let vid = vid_init(); let txn = vec![0u8]; - tracing::error!("here network task1"); let vid_disperse = vid.disperse(&txn).unwrap(); let block_commitment = vid_disperse.commit; let block = VIDBlockPayload::new(vec![VIDTransaction(txn)], block_commitment); @@ -59,7 +58,6 @@ async fn test_network_task() { let quorum_proposal = build_quorum_proposal(&handle, priv_key, 2).await; // TODO for now reuse the same block commitment and signature as DA committee // https://github.com/EspressoSystems/jellyfish/issues/369 - tracing::error!("here network task2"); let da_vid_disperse = Proposal { data: VidDisperse { view_number: da_proposal.data.view_number, diff --git a/crates/types/src/block_impl.rs b/crates/types/src/block_impl.rs index 79b0ce234b..bfe4ba6e59 100644 --- a/crates/types/src/block_impl.rs +++ b/crates/types/src/block_impl.rs @@ -113,7 +113,6 @@ impl TestableBlock for VIDBlockPayload { let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); let txn = vec![0u8]; - tracing::error!("here genesis"); let vid_disperse = vid.disperse(&txn).unwrap(); VIDBlockPayload::new(vec![VIDTransaction(txn)], vid_disperse.commit) } From a2759e258b3d368b76c855df7136e9ad7ddb622a Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Thu, 21 Sep 2023 18:44:58 -0700 Subject: [PATCH 08/37] Reorder events --- crates/task-impls/src/consensus.rs | 2 +- crates/task-impls/src/da.rs | 3 --- crates/task-impls/src/transactions.rs | 9 +++++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index b9a10e3d6e..4436e80de2 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -80,7 +80,7 @@ pub struct SequencingConsensusTaskState< pub consensus: Arc>>>, /// View timeout from config. pub timeout: u64, - /// View number this view is executing in + /// View number this view is executing in. pub cur_view: TYPES::Time, /// Current block submitted to DA diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index fe0a6ed311..5c4fb0fea3 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -643,9 +643,6 @@ where // Brodcast DA proposal // TODO ED We should send an event to do this, but just getting it to work for now - self.event_stream - .publish(SequencingHotShotEvent::SendDABlockData(block.clone())) - .await; // if let Err(e) = self.api.send_da_broadcast(message.clone()).await { // consensus.metrics.failed_to_send_messages.add(1); // warn!(?message, ?e, "Could not broadcast leader proposal"); diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index c01cf1ca2b..4aca5299f5 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -235,7 +235,6 @@ where drop(consensus); - let block; let txns = self.wait_for_transactions(parent_leaf).await?; debug!("Prepare VID shares"); @@ -255,12 +254,18 @@ where txns_flatten.extend(txn.bytes()); } let vid_disperse = vid.disperse(&txns_flatten).unwrap(); - block = VIDBlockPayload::new(txns, vid_disperse.commit); + let block = VIDBlockPayload::new(txns, vid_disperse.commit); + // TODO (Keyao) Is the order of the following events and events in the original + // DA task correct? self.event_stream .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) .await; + self.event_stream + .publish(SequencingHotShotEvent::SendDABlockData(block.clone())) + .await; + self.event_stream .publish(SequencingHotShotEvent::VidDisperseSend( Proposal { From 9fbdc95547865fb9ad73a5f569be8d233be57de6 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Thu, 21 Sep 2023 21:44:24 -0700 Subject: [PATCH 09/37] Add a logging to make test_success pass --- crates/task-impls/src/transactions.rs | 20 ++++++++++++-------- crates/types/src/block_impl.rs | 8 -------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 4aca5299f5..2e46ee8869 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -330,11 +330,14 @@ where loop { let all_txns = self.transactions.cloned().await; + tracing::error!("All txns {:?}", all_txns); debug!("Size of transactions: {}", all_txns.len()); - let unclaimed_txns: Vec<_> = all_txns - .iter() - .filter(|(txn_hash, _txn)| !previous_used_txns.contains(txn_hash)) - .collect(); + // TODO (Keyao) How to prevent duplicate txn now that we've removed the ID? + // let unclaimed_txns: Vec<_> = all_txns + // .iter() + // .filter(|(txn_hash, _txn)| !previous_used_txns.contains(txn_hash)) + // .collect(); + let unclaimed_txns = all_txns; let time_past = task_start_time.elapsed(); if unclaimed_txns.len() < self.api.min_transactions() @@ -363,11 +366,12 @@ where let txns: Vec = all_txns .iter() .filter_map(|(txn_hash, txn)| { - if previous_used_txns.contains(txn_hash) { - None - } else { + // TODO (Keyao) How to prevent duplicate txn now that we've removed the ID? + // if previous_used_txns.contains(txn_hash) { + // None + // } else { Some(txn.clone()) - } + // } }) .collect(); Some(txns) diff --git a/crates/types/src/block_impl.rs b/crates/types/src/block_impl.rs index bfe4ba6e59..4677cd5ab6 100644 --- a/crates/types/src/block_impl.rs +++ b/crates/types/src/block_impl.rs @@ -37,14 +37,6 @@ impl Transaction for VIDTransaction { } } -impl VIDTransaction { - /// create a new transaction - #[must_use] - pub fn new() -> Self { - Self(Vec::new()) - } -} - /// The error type for block payload. #[derive(Snafu, Debug)] pub enum BlockPayloadError { From e8d34a2748eb153c339e725b2cf455b20136fc44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 09:17:52 -0400 Subject: [PATCH 10/37] Bump blake3 from 1.4.1 to 1.5.0 (#1800) Bumps [blake3](https://github.com/BLAKE3-team/BLAKE3) from 1.4.1 to 1.5.0. - [Release notes](https://github.com/BLAKE3-team/BLAKE3/releases) - [Commits](https://github.com/BLAKE3-team/BLAKE3/compare/1.4.1...1.5.0) --- updated-dependencies: - dependency-name: blake3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e18e2095ed..46273bbc72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1003,9 +1003,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" dependencies = [ "arrayref", "arrayvec", diff --git a/Cargo.toml b/Cargo.toml index c1a4d45a6d..6fe925a50c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ bitvec = { version = "1.0.1", default-features = false, features = [ "atomic", "serde", ] } -blake3 = "1.4" +blake3 = "1.5" commit = { git = "https://github.com/EspressoSystems/commit", tag = "0.2.2" } custom_debug = "0.5" digest = "0.10" From 0c32b953475ae706d4377dd6f13a4a3f8bebcc31 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Fri, 22 Sep 2023 16:14:15 -0700 Subject: [PATCH 11/37] Make tests pass --- crates/orchestrator/default-libp2p-run-config.toml | 2 +- crates/orchestrator/default-run-config.toml | 2 +- crates/orchestrator/default-web-server-run-config.toml | 2 +- crates/task-impls/src/da.rs | 10 ++++------ crates/task-impls/src/transactions.rs | 7 +------ crates/testing/src/test_builder.rs | 6 +++--- crates/testing/tests/da_task.rs | 4 ---- 7 files changed, 11 insertions(+), 22 deletions(-) diff --git a/crates/orchestrator/default-libp2p-run-config.toml b/crates/orchestrator/default-libp2p-run-config.toml index 5757f4d9f9..220935614e 100644 --- a/crates/orchestrator/default-libp2p-run-config.toml +++ b/crates/orchestrator/default-libp2p-run-config.toml @@ -75,5 +75,5 @@ secs = 0 nanos = 0 [config.propose_max_round_time] -secs = 1 +secs = 2 nanos = 0 diff --git a/crates/orchestrator/default-run-config.toml b/crates/orchestrator/default-run-config.toml index fe34d75811..b8a4b19478 100644 --- a/crates/orchestrator/default-run-config.toml +++ b/crates/orchestrator/default-run-config.toml @@ -56,7 +56,7 @@ secs = 0 nanos = 0 [config.propose_max_round_time] -secs = 1 +secs = 2 nanos = 0 [web_server_config] diff --git a/crates/orchestrator/default-web-server-run-config.toml b/crates/orchestrator/default-web-server-run-config.toml index 0ea0f86ccf..28229f4d76 100644 --- a/crates/orchestrator/default-web-server-run-config.toml +++ b/crates/orchestrator/default-web-server-run-config.toml @@ -57,7 +57,7 @@ secs = 0 nanos = 0 [config.propose_max_round_time] -secs = 1 +secs = 2 nanos = 0 [web_server_config] diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index 5c4fb0fea3..6b3ba021a5 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -643,12 +643,10 @@ where // Brodcast DA proposal // TODO ED We should send an event to do this, but just getting it to work for now - // if let Err(e) = self.api.send_da_broadcast(message.clone()).await { - // consensus.metrics.failed_to_send_messages.add(1); - // warn!(?message, ?e, "Could not broadcast leader proposal"); - // } else { - // consensus.metrics.outgoing_broadcast_messages.add(1); - // } + self.event_stream + .publish(SequencingHotShotEvent::SendDABlockData(block.clone())) + .await; + self.event_stream .publish(SequencingHotShotEvent::DAProposalSend( message.clone(), diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 2e46ee8869..08854a98bb 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -262,10 +262,6 @@ where .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) .await; - self.event_stream - .publish(SequencingHotShotEvent::SendDABlockData(block.clone())) - .await; - self.event_stream .publish(SequencingHotShotEvent::VidDisperseSend( Proposal { @@ -330,7 +326,6 @@ where loop { let all_txns = self.transactions.cloned().await; - tracing::error!("All txns {:?}", all_txns); debug!("Size of transactions: {}", all_txns.len()); // TODO (Keyao) How to prevent duplicate txn now that we've removed the ID? // let unclaimed_txns: Vec<_> = all_txns @@ -370,7 +365,7 @@ where // if previous_used_txns.contains(txn_hash) { // None // } else { - Some(txn.clone()) + Some(txn.clone()) // } }) .collect(); diff --git a/crates/testing/src/test_builder.rs b/crates/testing/src/test_builder.rs index 326debb69b..3515f04368 100644 --- a/crates/testing/src/test_builder.rs +++ b/crates/testing/src/test_builder.rs @@ -124,7 +124,7 @@ impl TestMetadata { } } - /// Default setting with 20 nodes and 10 views of successful views. + /// Default setting with 20 nodes and 8 views of successful views. pub fn default_more_nodes_less_success() -> TestMetadata { TestMetadata { total_nodes: 20, @@ -139,11 +139,11 @@ impl TestMetadata { completion_task_description: CompletionTaskDescription::TimeBasedCompletionTaskBuilder( TimeBasedCompletionTaskDescription { // Increase the duration to get the expected number of successful views. - duration: Duration::new(40, 0), + duration: Duration::new(200, 0), }, ), overall_safety_properties: OverallSafetyPropertiesDescription { - num_successful_views: 10, + num_successful_views: 8, ..Default::default() }, ..TestMetadata::default() diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index 7c8b389d95..f1b1744884 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -103,10 +103,6 @@ async fn test_da_task() { let da_vote = committee_exchange.create_da_message(block.commit(), ViewNumber::new(2), vote_token); output.insert(SequencingHotShotEvent::DAVoteSend(da_vote), 1); - output.insert( - SequencingHotShotEvent::VidDisperseSend(vid_proposal.clone(), pub_key), - 1, - ); let vote_token = committee_exchange .make_vote_token(ViewNumber::new(2)) From 5782e457f7033301f9df093da1868aa1c486f814 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 24 Sep 2023 00:18:22 +0000 Subject: [PATCH 12/37] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'cargo-careful': 'github:RalfJung/cargo-careful/7e172de9330960658f48752c685ef34acc2e47a8' (2023-08-30) → 'github:RalfJung/cargo-careful/a338cfcfe817c6a488425db9a789fbfad09968b8' (2023-09-22) • Updated input 'fenix': 'github:nix-community/fenix/529f3af3d0e02a7b474c427464b166c36c531c4e' (2023-09-18) → 'github:nix-community/fenix/3605f6c31ac62e055c0ab0dbfa251fa96285109d' (2023-09-23) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/05666441bafd6010787a4097a6bd44266ad21018' (2023-09-17) → 'github:rust-lang/rust-analyzer/2b580a1f3c7bf7f2dd6d1462282362b80a6a3d91' (2023-09-22) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/5148520bfab61f99fd25fb9ff7bfbb50dad3c9db' (2023-09-17) → 'github:NixOS/nixpkgs/e12483116b3b51a185a33a272bf351e357ba9a99' (2023-09-21) --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index ec130ae4cd..c29e31ee27 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "cargo-careful": { "flake": false, "locked": { - "lastModified": 1693403352, - "narHash": "sha256-Ra2HtHzJvYoYslT7ryLi6rFoa/37gVJZ92/92zXtd7o=", + "lastModified": 1695361840, + "narHash": "sha256-PEoVeYjyy6xMp0T5HNYKgZPIsthMB3/SRT782D8YWdI=", "owner": "RalfJung", "repo": "cargo-careful", - "rev": "7e172de9330960658f48752c685ef34acc2e47a8", + "rev": "a338cfcfe817c6a488425db9a789fbfad09968b8", "type": "github" }, "original": { @@ -41,11 +41,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1695018106, - "narHash": "sha256-kZd7//cau0fRFqokaC9olL82j60c02yQH3sGAPSAm6Q=", + "lastModified": 1695449989, + "narHash": "sha256-A4KxWCgaT1BSVY99o+FZ841U/5yf5hKJmztwrBdvboM=", "owner": "nix-community", "repo": "fenix", - "rev": "529f3af3d0e02a7b474c427464b166c36c531c4e", + "rev": "3605f6c31ac62e055c0ab0dbfa251fa96285109d", "type": "github" }, "original": { @@ -72,11 +72,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694948089, - "narHash": "sha256-d2B282GmQ9o8klc22/Rbbbj6r99EnELQpOQjWMyv0rU=", + "lastModified": 1695318763, + "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5148520bfab61f99fd25fb9ff7bfbb50dad3c9db", + "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", "type": "github" }, "original": { @@ -99,11 +99,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1694973195, - "narHash": "sha256-+d/GW4MyksvJmNoQLJMpKxApuZTVwaT+yuxxR/Cc/BE=", + "lastModified": 1695398941, + "narHash": "sha256-BejjVu84wXk8G1dZuu66r8kz567aAymfaiYgXpMRNqU=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "05666441bafd6010787a4097a6bd44266ad21018", + "rev": "2b580a1f3c7bf7f2dd6d1462282362b80a6a3d91", "type": "github" }, "original": { From 317825f9877177c745e34c788d1f3d59703329a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:30:08 -0400 Subject: [PATCH 13/37] Bump time from 0.3.28 to 0.3.29 (#1808) Bumps [time](https://github.com/time-rs/time) from 0.3.28 to 0.3.29. - [Release notes](https://github.com/time-rs/time/releases) - [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md) - [Commits](https://github.com/time-rs/time/compare/v0.3.28...v0.3.29) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 32 ++++++++++++++++---------------- Cargo.toml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46273bbc72..003a8d52df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -526,7 +526,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -2612,7 +2612,7 @@ dependencies = [ "sha3", "snafu", "surf-disco", - "time 0.3.28", + "time 0.3.29", "tokio", "toml 0.7.8", "tracing", @@ -2761,7 +2761,7 @@ dependencies = [ "rand_chacha 0.3.1", "serde", "snafu", - "time 0.3.28", + "time 0.3.29", "tokio", "tracing", ] @@ -2835,7 +2835,7 @@ dependencies = [ "sha2 0.10.7", "snafu", "tagged-base64 0.2.4", - "time 0.3.28", + "time 0.3.29", "tokio", "tracing", "typenum", @@ -5305,7 +5305,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.28", + "time 0.3.29", "yasna", ] @@ -5738,7 +5738,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros 2.3.3", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -5755,7 +5755,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros 3.3.0", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -6639,22 +6639,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ "deranged", "itoa 1.0.9", "serde", "time-core", - "time-macros 0.2.14", + "time-macros 0.2.15", ] [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" @@ -6668,9 +6668,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -7570,7 +7570,7 @@ dependencies = [ "oid-registry", "rusticata-macros", "thiserror", - "time 0.3.28", + "time 0.3.29", ] [[package]] @@ -7603,7 +7603,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.28", + "time 0.3.29", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6fe925a50c..e75fec35c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,7 @@ serde = { version = "1.0.188", features = ["derive"] } sha2 = "0.10" snafu = "0.7.5" surf-disco = { git = "https://github.com/EspressoSystems/surf-disco.git", tag = "v0.4.2" } -time = "0.3.28" +time = "0.3.29" toml = "0.7.8" tracing = "0.1.37" typenum = "1.17.0" From 27a55cee08b4185257f5e86501d4d3738fcaa5a6 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Mon, 25 Sep 2023 12:44:16 -0700 Subject: [PATCH 14/37] Add gh issue and cleanup --- crates/hotshot/src/tasks/mod.rs | 5 ++- crates/task-impls/src/transactions.rs | 49 ++++++++++++++------------- crates/types/src/block_impl.rs | 31 ++++++++++------- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index bed3b3b344..fafc703075 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -38,7 +38,7 @@ use hotshot_types::{ node_implementation::{ CommitteeEx, ExchangesType, NodeImplementation, NodeType, ViewSyncEx, }, - state::{ConsensusTime, TestableBlock}, + state::ConsensusTime, }, vote::{ViewSyncData, VoteType}, }; @@ -289,8 +289,7 @@ where consensus, timeout: handle.hotshot.inner.config.next_view_timeout, cur_view: TYPES::Time::new(0), - // TODO (Keyao) Shouldn't use test function. - block: ::genesis(), + block: VIDBlockPayload::genesis(), quorum_exchange: c_api.inner.exchanges.quorum_exchange().clone().into(), api: c_api.clone(), committee_exchange: c_api.inner.exchanges.committee_exchange().clone().into(), diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 08854a98bb..b986cc931f 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -7,7 +7,7 @@ use async_lock::RwLock; use bincode::config::Options; use commit::Commitment; use commit::Committable; -use either::{Either, Left, Right}; +use either::{Left, Right}; use hotshot_task::{ event_stream::{ChannelStream, EventStream}, global_registry::GlobalRegistry, @@ -239,14 +239,12 @@ where debug!("Prepare VID shares"); if !txns.is_empty() { - /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 + // TODO https://github.com/EspressoSystems/HotShot/issues/1693 const NUM_STORAGE_NODES: usize = 10; - /// TODO https://github.com/EspressoSystems/HotShot/issues/1693 + // TODO https://github.com/EspressoSystems/HotShot/issues/1693 const NUM_CHUNKS: usize = 5; - // TODO https://github.com/EspressoSystems/HotShot/issues/1686 let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); - let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); // TODO https://github.com/EspressoSystems/jellyfish/issues/375 let mut txns_flatten = Vec::new(); @@ -256,8 +254,6 @@ where let vid_disperse = vid.disperse(&txns_flatten).unwrap(); let block = VIDBlockPayload::new(txns, vid_disperse.commit); - // TODO (Keyao) Is the order of the following events and events in the original - // DA task correct? self.event_stream .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) .await; @@ -312,22 +308,25 @@ where #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Transaction Handling Task", level = "error")] async fn wait_for_transactions( &self, - parent_leaf: SequencingLeaf, + _parent_leaf: SequencingLeaf, ) -> Option> { let task_start_time = Instant::now(); + // TODO (Keyao) Investigate the use of transaction hash + // // let parent_leaf = self.parent_leaf().await?; - let previous_used_txns = match parent_leaf.deltas { - Either::Left(block) => block.contained_transactions(), - Either::Right(_commitment) => HashSet::new(), - }; + // let previous_used_txns = match parent_leaf.deltas { + // Either::Left(block) => block.contained_transactions(), + // Either::Right(_commitment) => HashSet::new(), + // }; let receiver = self.transactions.subscribe().await; loop { let all_txns = self.transactions.cloned().await; debug!("Size of transactions: {}", all_txns.len()); - // TODO (Keyao) How to prevent duplicate txn now that we've removed the ID? + // TODO (Keyao) Investigate the use of transaction hash + // // let unclaimed_txns: Vec<_> = all_txns // .iter() // .filter(|(txn_hash, _txn)| !previous_used_txns.contains(txn_hash)) @@ -358,17 +357,19 @@ where break; } let all_txns = self.transactions.cloned().await; - let txns: Vec = all_txns - .iter() - .filter_map(|(txn_hash, txn)| { - // TODO (Keyao) How to prevent duplicate txn now that we've removed the ID? - // if previous_used_txns.contains(txn_hash) { - // None - // } else { - Some(txn.clone()) - // } - }) - .collect(); + // TODO (Keyao) Investigate the use of transaction hash + // + let txns: Vec = all_txns.values().cloned().collect(); + // let txns: Vec = all_txns + // .iter() + // .filter_map(|(txn_hash, txn)| { + // if previous_used_txns.contains(txn_hash) { + // None + // } else { + // Some(txn.clone()) + // } + // }) + // .collect(); Some(txns) } diff --git a/crates/types/src/block_impl.rs b/crates/types/src/block_impl.rs index 4677cd5ab6..634adc2d4c 100644 --- a/crates/types/src/block_impl.rs +++ b/crates/types/src/block_impl.rs @@ -73,6 +73,23 @@ impl VIDBlockPayload { commitment, } } + + /// Create a genesis block payload with transaction bytes `vec![0]`. + /// # Panics + /// If the `VidScheme` construction fails. + #[must_use] + pub fn genesis() -> Self { + // TODO + const NUM_STORAGE_NODES: usize = 10; + // TODO + const NUM_CHUNKS: usize = 5; + // TODO + let srs = test_srs(NUM_STORAGE_NODES); + let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + let txn = vec![0]; + let vid_disperse = vid.disperse(&txn).unwrap(); + VIDBlockPayload::new(vec![VIDTransaction(txn)], vid_disperse.commit) + } } impl Committable for VIDBlockPayload { @@ -94,19 +111,7 @@ impl Display for VIDBlockPayload { impl TestableBlock for VIDBlockPayload { fn genesis() -> Self { - /// TODO - const NUM_STORAGE_NODES: usize = 10; - /// TODO - const NUM_CHUNKS: usize = 5; - - // TODO - let srs = test_srs(NUM_STORAGE_NODES); - - let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); - - let txn = vec![0u8]; - let vid_disperse = vid.disperse(&txn).unwrap(); - VIDBlockPayload::new(vec![VIDTransaction(txn)], vid_disperse.commit) + Self::genesis() } fn txn_count(&self) -> u64 { From 5e6f0e0ddaae934fd54f29bbcaf40097374d3772 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Mon, 25 Sep 2023 13:21:20 -0700 Subject: [PATCH 15/37] Add another issue and fix lint --- crates/orchestrator/default-libp2p-run-config.toml | 4 ++++ crates/task-impls/src/transactions.rs | 6 +----- crates/testing/src/task_helpers.rs | 4 +--- crates/types/src/block_impl.rs | 11 +++++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/crates/orchestrator/default-libp2p-run-config.toml b/crates/orchestrator/default-libp2p-run-config.toml index 220935614e..9fb6cb6a17 100644 --- a/crates/orchestrator/default-libp2p-run-config.toml +++ b/crates/orchestrator/default-libp2p-run-config.toml @@ -51,6 +51,8 @@ mesh_outbound_min = 2 mesh_n = 4 next_view_timeout = 10 propose_min_round_time = 0 +# TODO Update libp2p config to use consistent propose_max_round_time. +# propose_max_round_time = 10 online_time = 10 num_txn_per_round = 10 @@ -75,5 +77,7 @@ secs = 0 nanos = 0 [config.propose_max_round_time] +# TODO Update libp2p config to use consistent propose_max_round_time. +# secs = 2 nanos = 0 diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index b986cc931f..11475fdbcf 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -15,7 +15,7 @@ use hotshot_task::{ task_impls::HSTWithEvent, }; use hotshot_types::{ - block_impl::{VIDBlockPayload, VIDTransaction}, + block_impl::{VIDBlockPayload, VIDTransaction, NUM_CHUNKS, NUM_STORAGE_NODES}, certificate::DACertificate, consensus::Consensus, data::{SequencingLeaf, VidDisperse, VidScheme, VidSchemeTrait}, @@ -239,10 +239,6 @@ where debug!("Prepare VID shares"); if !txns.is_empty() { - // TODO https://github.com/EspressoSystems/HotShot/issues/1693 - const NUM_STORAGE_NODES: usize = 10; - // TODO https://github.com/EspressoSystems/HotShot/issues/1693 - const NUM_CHUNKS: usize = 5; // TODO https://github.com/EspressoSystems/HotShot/issues/1686 let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); diff --git a/crates/testing/src/task_helpers.rs b/crates/testing/src/task_helpers.rs index 1a8123a35b..f4e7fe49a8 100644 --- a/crates/testing/src/task_helpers.rs +++ b/crates/testing/src/task_helpers.rs @@ -13,7 +13,7 @@ use hotshot::{ use hotshot_task::event_stream::ChannelStream; use hotshot_task_impls::events::SequencingHotShotEvent; use hotshot_types::{ - block_impl::VIDBlockPayload, + block_impl::{VIDBlockPayload, NUM_CHUNKS, NUM_STORAGE_NODES}, data::{QuorumProposal, SequencingLeaf, VidScheme, ViewNumber}, message::{Message, Proposal}, traits::{ @@ -165,8 +165,6 @@ pub fn key_pair_for_id(node_id: u64) -> (::PrivateKey } pub fn vid_init() -> VidScheme { - const NUM_STORAGE_NODES: usize = 10; - const NUM_CHUNKS: usize = 5; let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap() } diff --git a/crates/types/src/block_impl.rs b/crates/types/src/block_impl.rs index 634adc2d4c..03a9ca3737 100644 --- a/crates/types/src/block_impl.rs +++ b/crates/types/src/block_impl.rs @@ -13,6 +13,13 @@ use serde::{Deserialize, Serialize}; use sha3::{Digest, Keccak256}; use snafu::Snafu; +// TODO +/// Number of storage nodes for VID initiation. +pub const NUM_STORAGE_NODES: usize = 10; +// TODO +/// Number of chunks for VID initiation. +pub const NUM_CHUNKS: usize = 5; + /// The transaction in a [`VIDBlockPayload`]. #[derive(Default, PartialEq, Eq, Hash, Serialize, Deserialize, Clone, Debug)] pub struct VIDTransaction(pub Vec); @@ -79,10 +86,6 @@ impl VIDBlockPayload { /// If the `VidScheme` construction fails. #[must_use] pub fn genesis() -> Self { - // TODO - const NUM_STORAGE_NODES: usize = 10; - // TODO - const NUM_CHUNKS: usize = 5; // TODO let srs = test_srs(NUM_STORAGE_NODES); let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); From 6115f4b84d6fe9a6c13b4d62b8311db5fa3d95a2 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:30:26 -0400 Subject: [PATCH 16/37] update quinn-proto transitive dependency (#1809) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 003a8d52df..9dcb401038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5161,9 +5161,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13f81c9a9d574310b8351f8666f5a93ac3b0069c45c28ad52c10291389a7cf9" +checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" dependencies = [ "bytes 1.4.0", "rand 0.8.5", From e329b5b50c764788778ccc323e14a0814b7b22d2 Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Mon, 25 Sep 2023 18:30:29 -0400 Subject: [PATCH 17/37] chore: Remove Committable for more types, use CommitmentBounds (#1812) * remove Committable from VoteMetaData type param * remove Committable from VoteToken * remove Committable from ConsensusExchange::Commitment assoc type (whoa that's big) * update commit package (for Send, Sync on Commitment) * WIP remove Committable from QuorumCertificate. there's a circular dependency QuorumCertificate -> SignedCertificate::Vote -> QuorumVote -> YesOrNoVote -> QuorumCertificate so remove Committable from all those, too. need an alternative to fake_commitment in order to proceed * use latest 'commit' for default_commitment_no_preimage() * lint, remove unneeded pub * fix merge bug, tests pass locally with lots of error logs * lint * use CommitmentBounds everywhere, fix ensuing build breaks * cargo fmt why didn't it run automatically for me? * lint again grrrrrrrrr --- Cargo.lock | 27 ++++++- Cargo.toml | 2 +- crates/hotshot/src/demo.rs | 2 +- crates/hotshot/src/lib.rs | 12 +-- crates/hotshot/src/tasks/mod.rs | 23 +++--- crates/hotshot/src/types/handle.rs | 8 +- crates/task-impls/src/consensus.rs | 44 +++++----- crates/task-impls/src/da.rs | 12 +-- crates/task-impls/src/events.rs | 10 +-- crates/task-impls/src/transactions.rs | 9 +-- crates/task-impls/src/view_sync.rs | 14 ++-- crates/testing/src/overall_safety_task.rs | 8 +- crates/types/src/certificate.rs | 46 ++++++----- crates/types/src/consensus.rs | 2 +- crates/types/src/data.rs | 29 ++++--- crates/types/src/event.rs | 3 +- crates/types/src/message.rs | 5 +- crates/types/src/traits/consensus_api.rs | 4 +- crates/types/src/traits/election.rs | 98 ++++++++++------------- crates/types/src/traits/storage.rs | 4 +- crates/types/src/vote.rs | 89 +++++++++----------- 21 files changed, 226 insertions(+), 225 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9dcb401038..740b12364b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1282,7 +1282,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "commit" version = "0.2.2" -source = "git+https://github.com/EspressoSystems/commit?tag=0.2.2#7e938186607f87da5fd642ce36313aaeab0cfaca" +source = "git+https://github.com/EspressoSystems/commit#100cb8f402e32d794b4d2213356227b7bfeb0e92" dependencies = [ "arbitrary", "ark-serialize 0.3.0", @@ -1294,7 +1294,7 @@ dependencies = [ "hex", "serde", "sha3", - "tagged-base64 0.2.4", + "tagged-base64 0.3.1", ] [[package]] @@ -6410,6 +6410,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "tagged-base64" +version = "0.3.1" +source = "git+https://github.com/EspressoSystems/tagged-base64.git?tag=0.3.1#9207d39ba7a9c11801511a7077ea4330b6173e44" +dependencies = [ + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "base64 0.13.1", + "crc-any", + "serde", + "snafu", + "tagged-base64-macros 0.3.1", +] + [[package]] name = "tagged-base64" version = "0.3.3" @@ -6445,6 +6459,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tagged-base64-macros" +version = "0.3.1" +source = "git+https://github.com/EspressoSystems/tagged-base64.git?tag=0.3.1#9207d39ba7a9c11801511a7077ea4330b6173e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "tagged-base64-macros" version = "0.3.3" diff --git a/Cargo.toml b/Cargo.toml index e75fec35c8..10990e7437 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ bitvec = { version = "1.0.1", default-features = false, features = [ "serde", ] } blake3 = "1.5" -commit = { git = "https://github.com/EspressoSystems/commit", tag = "0.2.2" } +commit = { git = "https://github.com/EspressoSystems/commit" } custom_debug = "0.5" digest = "0.10" either = { version = "1.8" } diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index feaed2fe6b..afe0a38bb3 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -179,7 +179,7 @@ where /// Provides a random [`QuorumCertificate`] pub fn random_quorum_certificate>( rng: &mut dyn rand::RngCore, -) -> QuorumCertificate { +) -> QuorumCertificate> { QuorumCertificate { // block_commitment: random_commitment(rng), leaf_commitment: random_commitment(rng), diff --git a/crates/hotshot/src/lib.rs b/crates/hotshot/src/lib.rs index 0f317c9410..0b9e78f2ee 100644 --- a/crates/hotshot/src/lib.rs +++ b/crates/hotshot/src/lib.rs @@ -47,7 +47,7 @@ use async_compatibility_layer::{ }; use async_lock::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; use async_trait::async_trait; -use commit::Committable; +use commit::{Commitment, Committable}; use custom_debug::Debug; use hotshot_task::{ event_stream::{ChannelStream, EventStream}, @@ -647,8 +647,8 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, Membership = MEMBERSHIP, > + 'static, CommitteeEx: ConsensusExchange< @@ -656,7 +656,7 @@ where Message, Proposal = DAProposal, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, Membership = MEMBERSHIP, > + 'static, ViewSyncEx: ConsensusExchange< @@ -664,7 +664,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, Membership = MEMBERSHIP, > + 'static, { @@ -1059,7 +1059,7 @@ impl> HotShotInitializer::genesis(); + let justify_qc = QuorumCertificate::>::genesis(); Ok(Self { inner: LEAF::new(time, justify_qc, genesis_block, state), diff --git a/crates/hotshot/src/tasks/mod.rs b/crates/hotshot/src/tasks/mod.rs index 6be415cd66..843309aef0 100644 --- a/crates/hotshot/src/tasks/mod.rs +++ b/crates/hotshot/src/tasks/mod.rs @@ -5,7 +5,7 @@ use crate::{ QuorumCertificate, SequencingQuorumEx, }; use async_compatibility_layer::art::async_sleep; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds}; use futures::FutureExt; use hotshot_task::{ boxed_sync, @@ -42,7 +42,6 @@ use hotshot_types::{ }, vote::{ViewSyncData, VoteType}, }; -use serde::Serialize; use std::{ collections::{HashMap, HashSet}, marker::PhantomData, @@ -69,9 +68,9 @@ pub async fn add_network_message_task< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, - COMMITTABLE: Committable + Serialize + Clone, + COMMITMENT: CommitmentBounds, PROPOSAL: ProposalType, - VOTE: VoteType>, + VOTE: VoteType, MEMBERSHIP: Membership, EXCHANGE: ConsensusExchange< TYPES, @@ -179,9 +178,9 @@ pub async fn add_network_event_task< Leaf = SequencingLeaf, ConsensusMessage = SequencingMessage, >, - COMMITTABLE: Committable + Serialize + Clone, + COMMITMENT: CommitmentBounds, PROPOSAL: ProposalType, - VOTE: VoteType>, + VOTE: VoteType, MEMBERSHIP: Membership, EXCHANGE: ConsensusExchange< TYPES, @@ -268,14 +267,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { let consensus = handle.hotshot.get_consensus(); @@ -365,7 +364,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { // build the da task @@ -434,7 +433,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { // build the transactions task @@ -508,7 +507,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { let api = HotShotSequencingConsensusApi { diff --git a/crates/hotshot/src/types/handle.rs b/crates/hotshot/src/types/handle.rs index 5b8e737c1a..35e79a78dd 100644 --- a/crates/hotshot/src/types/handle.rs +++ b/crates/hotshot/src/types/handle.rs @@ -190,7 +190,7 @@ impl + 'static> SystemContextHandl if let Ok(anchor_leaf) = self.storage().get_anchored_view().await { if anchor_leaf.view_number == TYPES::Time::genesis() { let leaf: I::Leaf = I::Leaf::from_stored_view(anchor_leaf); - let mut qc = QuorumCertificate::::genesis(); + let mut qc = QuorumCertificate::>::genesis(); qc.set_leaf_commitment(leaf.commit()); let event = Event { view_number: TYPES::Time::genesis(), @@ -226,7 +226,7 @@ impl + 'static> SystemContextHandl // ) -> Result< // ( // Vec<>::Leaf>, - // QuorumCertificate>::Leaf>, + // QuorumCertificate>::Leaf>>, // ), // HotShotError, // > { @@ -333,7 +333,7 @@ impl + 'static> SystemContextHandl #[cfg(feature = "hotshot-testing")] pub fn create_yes_message( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -342,7 +342,7 @@ impl + 'static> SystemContextHandl QuorumEx: ConsensusExchange< TYPES, Message, - Certificate = QuorumCertificate, + Certificate = QuorumCertificate>, >, { let inner = self.hotshot.inner.clone(); diff --git a/crates/task-impls/src/consensus.rs b/crates/task-impls/src/consensus.rs index ef4694a282..f83c309b14 100644 --- a/crates/task-impls/src/consensus.rs +++ b/crates/task-impls/src/consensus.rs @@ -64,14 +64,14 @@ pub struct SequencingConsensusTaskState< TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// The global task registry @@ -126,7 +126,7 @@ pub struct SequencingConsensusTaskState< pub id: u64, /// The most Recent QC we've formed from votes, if we've formed it. - pub qc: Option>, + pub qc: Option>>, } /// State for the vote collection task. This handles the building of a QC from a votes received @@ -138,8 +138,8 @@ pub struct VoteCollectionTaskState< TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, { /// the quorum exchange @@ -147,13 +147,13 @@ pub struct VoteCollectionTaskState< #[allow(clippy::type_complexity)] /// Accumulator for votes pub accumulator: Either< - > as SignedCertificate< + >> as SignedCertificate< TYPES, TYPES::Time, TYPES::VoteTokenType, Commitment>, >>::VoteAccumulator, - QuorumCertificate>, + QuorumCertificate>>, >, /// View which this vote collection task is collecting votes in pub cur_view: TYPES::Time, @@ -170,8 +170,8 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, { } @@ -190,8 +190,8 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, { match event { @@ -272,14 +272,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Consensus genesis leaf", level = "error")] @@ -1087,7 +1087,7 @@ where /// Sends a proposal if possible from the high qc we have pub async fn publish_proposal_if_able( &self, - _qc: QuorumCertificate, + _qc: QuorumCertificate>, view: TYPES::Time, ) -> bool { if !self.quorum_exchange.is_leader(view) { @@ -1213,14 +1213,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } @@ -1262,14 +1262,14 @@ where TYPES, Message, Proposal = QuorumProposal>, - Certificate = QuorumCertificate>, - Commitment = SequencingLeaf, + Certificate = QuorumCertificate>>, + Commitment = Commitment>, >, CommitteeEx: ConsensusExchange< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { if let SequencingHotShotEvent::Shutdown = event { diff --git a/crates/task-impls/src/da.rs b/crates/task-impls/src/da.rs index 9b1657324f..87a7b685a4 100644 --- a/crates/task-impls/src/da.rs +++ b/crates/task-impls/src/da.rs @@ -55,7 +55,7 @@ pub struct DATaskState< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// The state's api @@ -91,7 +91,7 @@ pub struct DAVoteCollectionTaskState< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// the committee exchange @@ -122,7 +122,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } @@ -140,7 +140,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { match event { @@ -252,7 +252,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// main task event handler @@ -741,7 +741,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } diff --git a/crates/task-impls/src/events.rs b/crates/task-impls/src/events.rs index de8e31fd03..f9fc7f8ba3 100644 --- a/crates/task-impls/src/events.rs +++ b/crates/task-impls/src/events.rs @@ -1,3 +1,5 @@ +use crate::view_sync::ViewSyncPhase; +use commit::Commitment; use hotshot_types::{ certificate::{DACertificate, QuorumCertificate}, data::{DAProposal, VidDisperse}, @@ -8,8 +10,6 @@ use hotshot_types::{ vote::{DAVote, QuorumVote, ViewSyncVote}, }; -use crate::view_sync::ViewSyncPhase; - /// All of the possible events that can be passed between Sequecning `HotShot` tasks #[derive(Eq, Hash, PartialEq, Debug, Clone)] pub enum SequencingHotShotEvent> { @@ -18,7 +18,7 @@ pub enum SequencingHotShotEvent> { /// A quorum proposal has been received from the network; handled by the consensus task QuorumProposalRecv(Proposal>, TYPES::SignatureKey), /// A quorum vote has been received from the network; handled by the consensus task - QuorumVoteRecv(QuorumVote), + QuorumVoteRecv(QuorumVote>), /// A DA proposal has been received from the network; handled by the DA task DAProposalRecv(Proposal>, TYPES::SignatureKey), /// A DA vote has been received by the network; handled by the DA task @@ -28,13 +28,13 @@ pub enum SequencingHotShotEvent> { /// Send a quorum proposal to the network; emitted by the leader in the consensus task QuorumProposalSend(Proposal>, TYPES::SignatureKey), /// Send a quorum vote to the next leader; emitted by a replica in the consensus task after seeing a valid quorum proposal - QuorumVoteSend(QuorumVote), + QuorumVoteSend(QuorumVote>), /// Send a DA proposal to the DA committee; emitted by the DA leader (which is the same node as the leader of view v + 1) in the DA task DAProposalSend(Proposal>, TYPES::SignatureKey), /// Send a DA vote to the DA leader; emitted by DA committee members in the DA task after seeing a valid DA proposal DAVoteSend(DAVote), /// The next leader has collected enough votes to form a QC; emitted by the next leader in the consensus task; an internal event only - QCFormed(QuorumCertificate), + QCFormed(QuorumCertificate>), /// The DA leader has collected enough votes to form a DAC; emitted by the DA leader in the DA task; sent to the entire network via the networking task DACSend(DACertificate, TYPES::SignatureKey), /// The current view has changed; emitted by the replica in the consensus task or replica in the view sync task; received by almost all other tasks diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index b41604376d..376cbbc661 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -5,8 +5,7 @@ use async_compatibility_layer::{ }; use async_lock::RwLock; use bincode::config::Options; -use commit::Commitment; -use commit::Committable; +use commit::{Commitment, Committable}; use either::{Either, Left, Right}; use hotshot_task::{ event_stream::{ChannelStream, EventStream}, @@ -56,7 +55,7 @@ pub struct TransactionTaskState< TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// The state's api @@ -100,7 +99,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { /// main task event handler @@ -342,7 +341,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { } diff --git a/crates/task-impls/src/view_sync.rs b/crates/task-impls/src/view_sync.rs index eaac060975..30f3df83b6 100644 --- a/crates/task-impls/src/view_sync.rs +++ b/crates/task-impls/src/view_sync.rs @@ -75,7 +75,7 @@ pub struct ViewSyncTaskState< Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { /// Registry to register sub tasks @@ -124,7 +124,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { } @@ -152,7 +152,7 @@ pub struct ViewSyncReplicaTaskState< Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { /// Timeout for view sync rounds @@ -195,7 +195,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { } @@ -270,7 +270,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { #[instrument(skip_all, fields(id = self.id, view = *self.current_view), name = "View Sync Main Task", level = "error")] @@ -620,7 +620,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { #[instrument(skip_all, fields(id = self.id, view = *self.current_view), name = "View Sync Replica Task", level = "error")] @@ -951,7 +951,7 @@ where Message, Proposal = ViewSyncCertificate, Certificate = ViewSyncCertificate, - Commitment = ViewSyncData, + Commitment = Commitment>, >, { /// Handles incoming events for the view sync relay task diff --git a/crates/testing/src/overall_safety_task.rs b/crates/testing/src/overall_safety_task.rs index 4bda48adcc..b2a9a88451 100644 --- a/crates/testing/src/overall_safety_task.rs +++ b/crates/testing/src/overall_safety_task.rs @@ -90,9 +90,13 @@ impl> TS for OverallSafety pub struct RoundResult> { /// Transactions that were submitted // pub txns: Vec, + /// Nodes that committed this round /// id -> (leaf, qc) - pub success_nodes: HashMap, QuorumCertificate)>, + // TODO GG: isn't it infeasible to store a Vec? + #[allow(clippy::type_complexity)] + success_nodes: HashMap, QuorumCertificate>)>, + /// Nodes that failed to commit this round pub failed_nodes: HashMap>>>, @@ -185,7 +189,7 @@ impl> RoundResult pub fn insert_into_result( &mut self, idx: usize, - result: (Vec, QuorumCertificate), + result: (Vec, QuorumCertificate>), maybe_block_size: Option, ) -> Option { self.success_nodes.insert(idx as u64, result.clone()); diff --git a/crates/types/src/certificate.rs b/crates/types/src/certificate.rs index 7018490e09..09c3235744 100644 --- a/crates/types/src/certificate.rs +++ b/crates/types/src/certificate.rs @@ -6,7 +6,7 @@ use crate::vote::QuorumVoteAccumulator; use crate::vote::ViewSyncVoteAccumulator; use crate::vote::VoteType; use crate::{ - data::{fake_commitment, serialize_signature, LeafType}, + data::serialize_signature, traits::{ election::{SignedCertificate, VoteData, VoteToken}, node_implementation::NodeType, @@ -16,13 +16,14 @@ use crate::{ vote::{DAVote, ViewSyncData, ViewSyncVote}, }; use bincode::Options; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds, Committable}; use espresso_systems_common::hotshot::tag; use hotshot_utils::bincode::bincode_opts; use serde::{Deserialize, Serialize}; use std::{ fmt::{self, Debug, Display, Formatter}, + hash::Hash, ops::Deref, }; use tracing::debug; @@ -49,12 +50,12 @@ pub struct DACertificate { /// /// A Quorum Certificate is a threshold signature of the `Leaf` being proposed, as well as some /// metadata, such as the `Stage` of consensus the quorum certificate was generated during. -#[derive(custom_debug::Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Hash)] +#[derive(custom_debug::Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq, Hash, Eq)] #[serde(bound(deserialize = ""))] -pub struct QuorumCertificate> { +pub struct QuorumCertificate { /// commitment to previous leaf #[debug(skip)] - pub leaf_commitment: Commitment, + pub leaf_commitment: COMMITMENT, /// Which view this QC relates to pub view_number: TYPES::Time, /// assembled signature for certificate aggregation @@ -63,7 +64,9 @@ pub struct QuorumCertificate> pub is_genesis: bool, } -impl> Display for QuorumCertificate { +impl Display + for QuorumCertificate +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( f, @@ -138,15 +141,15 @@ pub enum AssembledSignature { } /// Data from a vote needed to accumulate into a `SignedCertificate` -pub struct VoteMetaData { +pub struct VoteMetaData { /// Voter's public key pub encoded_key: EncodedPublicKey, /// Votes signature pub encoded_signature: EncodedSignature, /// Commitment to what's voted on. E.g. the leaf for a `QuorumCertificate` - pub commitment: Commitment, + pub commitment: COMMITMENT, /// Data of the vote, yes, no, timeout, or DA - pub data: VoteData>, + pub data: VoteData, /// The votes's token pub vote_token: T, /// View number for the vote @@ -156,12 +159,12 @@ pub struct VoteMetaData, } -impl> - SignedCertificate> - for QuorumCertificate +impl + SignedCertificate + for QuorumCertificate { - type Vote = QuorumVote; - type VoteAccumulator = QuorumVoteAccumulator, Self::Vote>; + type Vote = QuorumVote; + type VoteAccumulator = QuorumVoteAccumulator; fn from_signatures_and_commitment( signatures: AssembledSignature, @@ -191,11 +194,11 @@ impl> self.signatures.clone() } - fn leaf_commitment(&self) -> Commitment { + fn leaf_commitment(&self) -> COMMITMENT { self.leaf_commitment } - fn set_leaf_commitment(&mut self, commitment: Commitment) { + fn set_leaf_commitment(&mut self, commitment: COMMITMENT) { self.leaf_commitment = commitment; } @@ -204,8 +207,9 @@ impl> } fn genesis() -> Self { + // TODO GG need a new way to get fake commit now that we don't have Committable Self { - leaf_commitment: fake_commitment::(), + leaf_commitment: COMMITMENT::default_commitment_no_preimage(), view_number: ::genesis(), signatures: AssembledSignature::Genesis(), is_genesis: true, @@ -213,16 +217,14 @@ impl> } } -impl> Eq for QuorumCertificate {} - -impl> Committable - for QuorumCertificate +impl Committable + for QuorumCertificate { fn commit(&self) -> Commitment { let signatures_bytes = serialize_signature(&self.signatures); commit::RawCommitmentBuilder::new("Quorum Certificate Commitment") - .field("leaf commitment", self.leaf_commitment) + .var_size_field("leaf commitment", self.leaf_commitment.as_ref()) .u64_field("view number", *self.view_number.deref()) .constant_str("justify_qc signatures") .var_size_bytes(&signatures_bytes) diff --git a/crates/types/src/consensus.rs b/crates/types/src/consensus.rs index ce27d7a547..e10900aa7e 100644 --- a/crates/types/src/consensus.rs +++ b/crates/types/src/consensus.rs @@ -53,7 +53,7 @@ pub struct Consensus> { pub locked_view: TYPES::Time, /// the highqc per spec - pub high_qc: QuorumCertificate, + pub high_qc: QuorumCertificate>, /// A reference to the metrics trait #[debug(skip)] diff --git a/crates/types/src/data.rs b/crates/types/src/data.rs index 080355a195..95456393ed 100644 --- a/crates/types/src/data.rs +++ b/crates/types/src/data.rs @@ -9,7 +9,6 @@ use crate::{ ViewSyncCertificate, }, traits::{ - election::SignedCertificate, node_implementation::NodeType, signature_key::{EncodedPublicKey, SignatureKey}, state::{ConsensusTime, TestableBlock, TestableState}, @@ -132,7 +131,7 @@ where pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The hash of the parent `Leaf` /// So we can ask if it extends @@ -215,7 +214,7 @@ pub struct QuorumProposal> { pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// Possible timeout certificate. Only present if the justify_qc is not for the preceding view pub timeout_certificate: Option>, @@ -444,7 +443,7 @@ pub trait LeafType: /// Create a new leaf from its components. fn new( view_number: LeafTime, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, deltas: LeafBlock, state: LeafState, ) -> Self; @@ -457,7 +456,7 @@ pub trait LeafType: /// Change the height of this leaf. fn set_height(&mut self, height: u64); /// The QC linking this leaf to its parent in the chain. - fn get_justify_qc(&self) -> QuorumCertificate; + fn get_justify_qc(&self) -> QuorumCertificate>; /// Commitment to this leaf's parent. fn get_parent_commitment(&self) -> Commitment; /// The block contained in this leaf. @@ -531,11 +530,11 @@ pub struct ValidatingLeaf { pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The hash of the parent `Leaf` /// So we can ask if it extends - pub parent_commitment: Commitment>, + pub parent_commitment: Commitment, /// BlockPayload leaf wants to apply pub deltas: TYPES::BlockType, @@ -570,11 +569,11 @@ pub struct SequencingLeaf { pub height: u64, /// Per spec, justification - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The hash of the parent `SequencingLeaf` /// So we can ask if it extends - pub parent_commitment: Commitment>, + pub parent_commitment: Commitment, /// The block or block commitment to be applied pub deltas: Either>, @@ -644,7 +643,7 @@ impl LeafType for ValidatingLeaf { fn new( view_number: ::Time, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, deltas: ::BlockType, state: ::StateType, ) -> Self { @@ -673,7 +672,7 @@ impl LeafType for ValidatingLeaf { self.height = height; } - fn get_justify_qc(&self) -> QuorumCertificate { + fn get_justify_qc(&self) -> QuorumCertificate> { self.justify_qc.clone() } @@ -761,7 +760,7 @@ impl LeafType for SequencingLeaf { fn new( view_number: ::Time, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, deltas: ::BlockType, _state: ::StateType, ) -> Self { @@ -789,7 +788,7 @@ impl LeafType for SequencingLeaf { self.height = height; } - fn get_justify_qc(&self) -> QuorumCertificate { + fn get_justify_qc(&self) -> QuorumCertificate> { self.justify_qc.clone() } @@ -934,7 +933,7 @@ impl Committable for ValidatingLeaf { .u64(*self.justify_qc.view_number) .field( "justify_qc leaf commitment", - self.justify_qc.leaf_commitment(), + self.justify_qc.leaf_commitment, ) .constant_str("justify_qc signatures") .var_size_bytes(&signatures_bytes) @@ -966,7 +965,7 @@ impl Committable for SequencingLeaf { .u64(*self.justify_qc.view_number) .field( "justify_qc leaf commitment", - self.justify_qc.leaf_commitment(), + self.justify_qc.leaf_commitment, ) .constant_str("justify_qc signatures") .var_size_bytes(&signatures_bytes) diff --git a/crates/types/src/event.rs b/crates/types/src/event.rs index f33a39f8cd..5d091cd400 100644 --- a/crates/types/src/event.rs +++ b/crates/types/src/event.rs @@ -4,6 +4,7 @@ use crate::{ certificate::QuorumCertificate, data::LeafType, error::HotShotError, traits::node_implementation::NodeType, }; +use commit::Commitment; use std::sync::Arc; /// A status event emitted by a `HotShot` instance /// @@ -42,7 +43,7 @@ pub enum EventType> { /// /// Note that the QC for each additional leaf in the chain can be obtained from the leaf /// before it using - qc: Arc>, + qc: Arc>>, /// Optional information of the number of transactions in the block, for logging purposes. block_size: Option, }, diff --git a/crates/types/src/message.rs b/crates/types/src/message.rs index d5897c0ef8..c26de8bcef 100644 --- a/crates/types/src/message.rs +++ b/crates/types/src/message.rs @@ -15,6 +15,7 @@ use crate::{ }, vote::{DAVote, QuorumVote, ViewSyncVote, VoteType}, }; +use commit::Commitment; use derivative::Derivative; use either::Either::{self, Left, Right}; use serde::{Deserialize, Serialize}; @@ -149,7 +150,7 @@ where /// Message with a quorum proposal. Proposal(Proposal>, TYPES::SignatureKey), /// Message with a quorum vote. - Vote(QuorumVote, TYPES::SignatureKey), + Vote(QuorumVote>, TYPES::SignatureKey), /// Message with a view sync vote. ViewSyncVote(ViewSyncVote), /// Message with a view sync certificate. @@ -314,7 +315,7 @@ where Proposal(Proposal>), /// Message with a quorum vote. - Vote(QuorumVote), + Vote(QuorumVote>), /// Message with a view sync vote. ViewSyncVote(ViewSyncVote), diff --git a/crates/types/src/traits/consensus_api.rs b/crates/types/src/traits/consensus_api.rs index ab3f899944..08716a3d73 100644 --- a/crates/types/src/traits/consensus_api.rs +++ b/crates/types/src/traits/consensus_api.rs @@ -14,7 +14,7 @@ use crate::{ }, }; use async_trait::async_trait; - +use commit::Commitment; use std::{num::NonZeroUsize, sync::Arc, time::Duration}; /// The API that [`HotStuff`] needs to talk to the system, implemented for both validating and @@ -97,7 +97,7 @@ pub trait ConsensusSharedApi< &self, view_number: TYPES::Time, leaf_views: Vec, - decide_qc: QuorumCertificate, + decide_qc: QuorumCertificate>, ) { self.send_event(Event { view_number, diff --git a/crates/types/src/traits/election.rs b/crates/types/src/traits/election.rs index 7ccde773af..6b3ef7e790 100644 --- a/crates/types/src/traits/election.rs +++ b/crates/types/src/traits/election.rs @@ -34,7 +34,7 @@ use crate::{ }, }; use bincode::Options; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds, Committable}; use derivative::Derivative; use either::Either; use ethereum_types::U256; @@ -76,7 +76,7 @@ pub enum Checked { #[serde(bound(deserialize = ""))] pub enum VoteData where - COMMITMENT: for<'a> Deserialize<'a>, + COMMITMENT: CommitmentBounds, { /// Vote to provide availability for a block. DA(COMMITMENT), @@ -96,7 +96,7 @@ where impl VoteData where - COMMITMENT: for<'a> Deserialize<'a> + Clone, + COMMITMENT: CommitmentBounds, { /// Return the underlying commitment. #[must_use] @@ -105,14 +105,14 @@ where use VoteData::*; match self { DA(c) | Yes(c) | No(c) | Timeout(c) | ViewSyncPreCommit(c) | ViewSyncCommit(c) - | ViewSyncFinalize(c) => c.clone(), + | ViewSyncFinalize(c) => *c, } } } impl VoteData where - COMMITMENT: Serialize + for<'a> Deserialize<'a>, + COMMITMENT: CommitmentBounds, { #[must_use] /// Convert vote data into bytes. @@ -135,7 +135,6 @@ pub trait VoteToken: + PartialEq + Hash + Eq - + Committable { // type StakeTable; // type KeyPair: SignatureKey; @@ -161,7 +160,7 @@ pub trait ElectionConfig: pub trait SignedCertificate where Self: Send + Sync + Clone + Serialize + for<'a> Deserialize<'a>, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + COMMITMENT: CommitmentBounds, TOKEN: VoteToken, { /// `VoteType` that is used in this certificate @@ -267,9 +266,9 @@ pub trait ConsensusExchange: Send + Sync { type Proposal: ProposalType; /// A vote on a [`Proposal`](Self::Proposal). // TODO ED Make this equal Certificate vote (if possible?) - type Vote: VoteType>; + type Vote: VoteType; /// A [`SignedCertificate`] attesting to a decision taken by the committee. - type Certificate: SignedCertificate> + type Certificate: SignedCertificate + Hash + Eq; /// The committee eligible to make decisions. @@ -277,7 +276,7 @@ pub trait ConsensusExchange: Send + Sync { /// Network used by [`Membership`](Self::Membership) to communicate. type Networking: CommunicationChannel; /// Commitments to items which are the subject of proposals and decisions. - type Commitment: Committable + Serialize + for<'a> Deserialize<'a> + Clone; + type Commitment: CommitmentBounds; /// Join a [`ConsensusExchange`] with the given identity (`pk` and `sk`). fn create( @@ -330,13 +329,10 @@ pub trait ConsensusExchange: Send + Sync { } /// The contents of a vote on `commit`. - fn vote_data( - &self, - commit: Commitment, - ) -> VoteData>; + fn vote_data(&self, commit: Self::Commitment) -> VoteData; /// Validate a QC. - fn is_valid_cert(&self, qc: &Self::Certificate, commit: Commitment) -> bool { + fn is_valid_cert(&self, qc: &Self::Certificate, commit: Self::Commitment) -> bool { if qc.is_genesis() && qc.view_number() == TYPES::Time::genesis() { return true; } @@ -387,7 +383,7 @@ pub trait ConsensusExchange: Send + Sync { &self, encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, - data: VoteData>, + data: VoteData, vote_token: Checked, ) -> bool { let mut is_valid_vote_token = false; @@ -412,7 +408,7 @@ pub trait ConsensusExchange: Send + Sync { &self, key: &TYPES::SignatureKey, encoded_signature: &EncodedSignature, - data: &VoteData>, + data: &VoteData, vote_token: &Checked, ) -> bool { let is_valid_signature = key.validate(encoded_signature, data.get_commit().as_ref()); @@ -449,8 +445,8 @@ pub trait ConsensusExchange: Send + Sync { &self, encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, - leaf_commitment: Commitment, - vote_data: VoteData>, + leaf_commitment: Self::Commitment, + vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, accumlator: VoteAccumulator, @@ -468,21 +464,21 @@ pub trait ConsensusExchange: Send + Sync { TYPES, TYPES::Time, TYPES::VoteTokenType, - Commitment, + Self::Commitment, >>::VoteAccumulator, vote: &<>::Certificate as SignedCertificate< TYPES, TYPES::Time, TYPES::VoteTokenType, - Commitment, + Self::Commitment, >>::Vote, - _commit: &Commitment, + _commit: &Self::Commitment, ) -> Either< <>::Certificate as SignedCertificate< TYPES, TYPES::Time, TYPES::VoteTokenType, - Commitment, + Self::Commitment, >>::VoteAccumulator, Self::Certificate, > { @@ -685,7 +681,7 @@ impl< type Certificate = DACertificate; type Membership = MEMBERSHIP; type Networking = NETWORK; - type Commitment = TYPES::BlockType; + type Commitment = Commitment; fn create( entries: Vec<::StakeTableEntry>, @@ -717,10 +713,7 @@ impl< .make_vote_token(view_number, &self.private_key) } - fn vote_data( - &self, - commit: Commitment, - ) -> VoteData> { + fn vote_data(&self, commit: Self::Commitment) -> VoteData { VoteData::DA(commit) } @@ -730,8 +723,8 @@ impl< &self, encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, - leaf_commitment: Commitment, - vote_data: VoteData>, + leaf_commitment: Self::Commitment, + vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, accumlator: VoteAccumulator, @@ -815,7 +808,7 @@ pub trait QuorumExchangeType, /// Create a message with a negative vote on validating or commitment proposal. fn create_no_message>( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -826,7 +819,7 @@ pub trait QuorumExchangeType, /// Create a message with a timeout vote on validating or commitment proposal. fn create_timeout_message>( &self, - justify_qc: QuorumCertificate, + justify_qc: QuorumCertificate>, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, ) -> GeneralConsensusMessage @@ -873,7 +866,7 @@ impl< /// Create a message with a positive vote on validating or commitment proposal. fn create_yes_message>( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -952,7 +945,7 @@ impl< /// Create a message with a negative vote on validating or commitment proposal. fn create_no_message>( &self, - justify_qc_commitment: Commitment>, + justify_qc_commitment: Commitment>>, leaf_commitment: Commitment, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, @@ -974,7 +967,7 @@ impl< /// Create a message with a timeout vote on validating or commitment proposal. fn create_timeout_message>( &self, - high_qc: QuorumCertificate, + high_qc: QuorumCertificate>, current_view: TYPES::Time, vote_token: TYPES::VoteTokenType, ) -> GeneralConsensusMessage @@ -1003,11 +996,11 @@ impl< for QuorumExchange { type Proposal = PROPOSAL; - type Vote = QuorumVote; - type Certificate = QuorumCertificate; + type Vote = QuorumVote>; + type Certificate = QuorumCertificate>; type Membership = MEMBERSHIP; type Networking = NETWORK; - type Commitment = LEAF; + type Commitment = Commitment; fn create( entries: Vec<::StakeTableEntry>, @@ -1033,10 +1026,7 @@ impl< &self.network } - fn vote_data( - &self, - commit: Commitment, - ) -> VoteData> { + fn vote_data(&self, commit: Self::Commitment) -> VoteData { VoteData::Yes(commit) } @@ -1047,12 +1037,13 @@ impl< encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, leaf_commitment: Commitment, - vote_data: VoteData>, + vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, - accumlator: VoteAccumulator, + accumlator: VoteAccumulator, TYPES>, _relay: Option, - ) -> Either, Self::Certificate> { + ) -> Either, TYPES>, Self::Certificate> + { let meta = VoteMetaData { encoded_key: encoded_key.clone(), encoded_signature: encoded_signature.clone(), @@ -1369,7 +1360,7 @@ impl< type Certificate = ViewSyncCertificate; type Membership = MEMBERSHIP; type Networking = NETWORK; - type Commitment = ViewSyncData; + type Commitment = Commitment>; fn create( entries: Vec<::StakeTableEntry>, @@ -1395,10 +1386,7 @@ impl< &self.network } - fn vote_data( - &self, - _commit: Commitment, - ) -> VoteData> { + fn vote_data(&self, _commit: Self::Commitment) -> VoteData { unimplemented!() } @@ -1407,13 +1395,15 @@ impl< encoded_key: &EncodedPublicKey, encoded_signature: &EncodedSignature, leaf_commitment: Commitment>, - vote_data: VoteData>, + vote_data: VoteData, vote_token: TYPES::VoteTokenType, view_number: TYPES::Time, - accumlator: VoteAccumulator, TYPES>, + accumlator: VoteAccumulator>, TYPES>, relay: Option, - ) -> Either, TYPES>, Self::Certificate> - { + ) -> Either< + VoteAccumulator>, TYPES>, + Self::Certificate, + > { let meta = VoteMetaData { encoded_key: encoded_key.clone(), encoded_signature: encoded_signature.clone(), diff --git a/crates/types/src/traits/storage.rs b/crates/types/src/traits/storage.rs index 20c8f87f9a..122698486c 100644 --- a/crates/types/src/traits/storage.rs +++ b/crates/types/src/traits/storage.rs @@ -132,7 +132,7 @@ pub struct StoredView> { /// The parent of this view pub parent: Commitment, /// The justify QC of this view. See the hotstuff paper for more information on this. - pub justify_qc: QuorumCertificate, + pub justify_qc: QuorumCertificate>, /// The state of this view pub state: LEAF::MaybeState, /// The deltas of this view @@ -156,7 +156,7 @@ where /// /// Note that this will set the `parent` to `LeafHash::default()`, so this will not have a parent. pub fn from_qc_block_and_state( - qc: QuorumCertificate, + qc: QuorumCertificate>, deltas: LEAF::DeltasType, state: LEAF::MaybeState, height: u64, diff --git a/crates/types/src/vote.rs b/crates/types/src/vote.rs index c27225e4af..9e232b755a 100644 --- a/crates/types/src/vote.rs +++ b/crates/types/src/vote.rs @@ -5,7 +5,6 @@ use crate::{ certificate::{AssembledSignature, QuorumCertificate}, - data::LeafType, traits::{ election::{VoteData, VoteToken}, node_implementation::NodeType, @@ -14,7 +13,7 @@ use crate::{ }; use bincode::Options; use bitvec::prelude::*; -use commit::{Commitment, Committable}; +use commit::{Commitment, CommitmentBounds, Committable}; use either::Either; use ethereum_types::U256; use hotshot_utils::bincode::bincode_opts; @@ -29,7 +28,7 @@ use std::{ use tracing::error; /// The vote sent by consensus messages. -pub trait VoteType Deserialize<'a> + Serialize + Clone>: +pub trait VoteType: Debug + Clone + 'static + Serialize + for<'a> Deserialize<'a> + Send + Sync + PartialEq { /// Get the view this vote was cast for @@ -63,29 +62,29 @@ pub struct DAVote { /// A positive or negative vote on validating or commitment proposal. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub struct YesOrNoVote> { +pub struct YesOrNoVote { /// TODO we should remove this /// this is correct, but highly inefficient /// we should check a cache, and if that fails request the qc - pub justify_qc_commitment: Commitment>, + pub justify_qc_commitment: Commitment>, /// The signature share associated with this vote pub signature: (EncodedPublicKey, EncodedSignature), /// The leaf commitment being voted on. - pub leaf_commitment: Commitment, + pub leaf_commitment: COMMITMENT, /// The view this vote was cast for pub current_view: TYPES::Time, /// The vote token generated by this replica pub vote_token: TYPES::VoteTokenType, /// The vote data this vote is signed over - pub vote_data: VoteData>, + pub vote_data: VoteData, } /// A timeout vote. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub struct TimeoutVote> { +pub struct TimeoutVote { /// The highest valid QC this node knows about - pub high_qc: QuorumCertificate, + pub high_qc: QuorumCertificate, /// The signature share associated with this vote pub signature: (EncodedPublicKey, EncodedSignature), /// The view this vote was cast for @@ -188,13 +187,13 @@ impl ViewSyncVote { /// Votes on validating or commitment proposal. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[serde(bound(deserialize = ""))] -pub enum QuorumVote> { +pub enum QuorumVote { /// Posivite vote. - Yes(YesOrNoVote), + Yes(YesOrNoVote), /// Negative vote. - No(YesOrNoVote), + No(YesOrNoVote), /// Timeout vote. - Timeout(TimeoutVote), + Timeout(TimeoutVote), } impl VoteType> for DAVote { @@ -224,8 +223,8 @@ impl DAVote { } } -impl> VoteType> - for QuorumVote +impl VoteType + for QuorumVote { fn get_view(&self) -> TYPES::Time { match self { @@ -240,7 +239,7 @@ impl> VoteType EncodedSignature { self.signature() } - fn get_data(&self) -> VoteData> { + fn get_data(&self) -> VoteData { match self { QuorumVote::Yes(v) | QuorumVote::No(v) => v.vote_data.clone(), QuorumVote::Timeout(_) => unimplemented!(), @@ -254,7 +253,7 @@ impl> VoteType> QuorumVote { +impl QuorumVote { /// Get the encoded signature. pub fn signature(&self) -> EncodedSignature { @@ -320,7 +319,7 @@ pub trait Accumulator: Sized { /// Accumulator trait used to accumulate votes into an `AssembledSignature` pub trait Accumulator2< TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + COMMITMENT: CommitmentBounds, VOTE: VoteType, >: Sized { @@ -338,7 +337,7 @@ pub trait Accumulator2< /// Accumulates DA votes pub struct DAVoteAccumulator< TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + COMMITMENT: CommitmentBounds, VOTE: VoteType, > { /// Map of all da signatures accumlated so far @@ -353,11 +352,8 @@ pub struct DAVoteAccumulator< pub phantom: PhantomData, } -impl< - TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone + Copy + PartialEq + Eq + Hash, - VOTE: VoteType, - > Accumulator2 for DAVoteAccumulator +impl> + Accumulator2 for DAVoteAccumulator { fn append( mut self, @@ -429,7 +425,7 @@ impl< /// Accumulate quorum votes pub struct QuorumVoteAccumulator< TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + COMMITMENT: CommitmentBounds, VOTE: VoteType, > { /// Map of all signatures accumlated so far @@ -451,11 +447,8 @@ pub struct QuorumVoteAccumulator< pub phantom: PhantomData, } -impl< - TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone + Copy + PartialEq + Eq + Hash, - VOTE: VoteType, - > Accumulator2 for QuorumVoteAccumulator +impl> + Accumulator2 for QuorumVoteAccumulator { fn append( mut self, @@ -560,7 +553,7 @@ impl< /// Accumulates view sync votes pub struct ViewSyncVoteAccumulator< TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + COMMITMENT: CommitmentBounds, VOTE: VoteType, > { /// Map of all pre_commit signatures accumlated so far @@ -582,11 +575,8 @@ pub struct ViewSyncVoteAccumulator< pub phantom: PhantomData, } -impl< - TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone + Copy + PartialEq + Eq + Hash, - VOTE: VoteType, - > Accumulator2 for ViewSyncVoteAccumulator +impl> + Accumulator2 for ViewSyncVoteAccumulator { #[allow(clippy::too_many_lines)] fn append( @@ -734,18 +724,15 @@ impl< /// Placeholder accumulator; will be replaced by accumulator for each certificate type pub struct AccumulatorPlaceholder< TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, + COMMITMENT: CommitmentBounds, VOTE: VoteType, > { /// Phantom data to make compiler happy pub phantom: PhantomData<(TYPES, VOTE, COMMITMENT)>, } -impl< - TYPES: NodeType, - COMMITMENT: for<'a> Deserialize<'a> + Serialize + Clone, - VOTE: VoteType, - > Accumulator2 for AccumulatorPlaceholder +impl> + Accumulator2 for AccumulatorPlaceholder { fn append( self, @@ -771,11 +758,7 @@ type VoteMap = HashMap< /// respectively. /// /// TODO GG used only in election.rs; move this to there and make it private? -pub struct VoteAccumulator< - TOKEN, - COMMITMENT: Serialize + for<'a> Deserialize<'a> + Clone, - TYPES: NodeType, -> { +pub struct VoteAccumulator { /// Map of all signatures accumlated so far pub total_vote_outcomes: VoteMap, /// Map of all da signatures accumlated so far @@ -800,23 +783,23 @@ pub struct VoteAccumulator< pub signers: BitVec, } -impl +impl Accumulator< ( - Commitment, + COMMITMENT, ( EncodedPublicKey, ( EncodedSignature, Vec<::StakeTableEntry>, usize, - VoteData>, + VoteData, TOKEN, ), ), ), AssembledSignature, - > for VoteAccumulator, TYPES> + > for VoteAccumulator where TOKEN: Clone + VoteToken, { @@ -824,14 +807,14 @@ where fn append( mut self, val: ( - Commitment, + COMMITMENT, ( EncodedPublicKey, ( EncodedSignature, Vec<::StakeTableEntry>, usize, - VoteData>, + VoteData, TOKEN, ), ), From f6cac67c2834f1faedb4aa76da97f150e41dfcf7 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Mon, 25 Sep 2023 19:50:30 -0400 Subject: [PATCH 18/37] Persist Kademlia cache to disk (#1773) --- .gitignore | 1 + .../src/traits/networking/libp2p_network.rs | 47 +-- .../src/network/behaviours/dht/cache.rs | 325 ++++++++++++++++++ .../network/behaviours/{dht.rs => dht/mod.rs} | 52 ++- crates/libp2p-networking/src/network/mod.rs | 12 +- crates/libp2p-networking/src/network/node.rs | 4 +- .../src/network/node/config.rs | 5 + .../src/network/node/handle.rs | 169 +-------- crates/libp2p-networking/tests/common/mod.rs | 10 +- crates/libp2p-networking/tests/counter.rs | 31 +- 10 files changed, 422 insertions(+), 234 deletions(-) create mode 100644 crates/libp2p-networking/src/network/behaviours/dht/cache.rs rename crates/libp2p-networking/src/network/behaviours/{dht.rs => dht/mod.rs} (94%) diff --git a/.gitignore b/.gitignore index 839d85dc3d..ff07ca5941 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /target_dirs /.vscode/settings.json **/.DS_Store +*.cache \ No newline at end of file diff --git a/crates/hotshot/src/traits/networking/libp2p_network.rs b/crates/hotshot/src/traits/networking/libp2p_network.rs index da8784e0a7..ebb68e7d01 100644 --- a/crates/hotshot/src/traits/networking/libp2p_network.rs +++ b/crates/hotshot/src/traits/networking/libp2p_network.rs @@ -5,14 +5,14 @@ use super::NetworkingMetrics; use crate::NodeImplementation; use async_compatibility_layer::{ - art::{async_block_on, async_sleep, async_spawn, async_timeout}, + art::{async_block_on, async_sleep, async_spawn}, channel::{unbounded, UnboundedReceiver, UnboundedSendError, UnboundedSender}, }; use async_lock::RwLock; use async_trait::async_trait; use bimap::BiHashMap; use bincode::Options; -use hotshot_constants::{KAD_DEFAULT_REPUB_INTERVAL_SEC, LOOK_AHEAD}; +use hotshot_constants::LOOK_AHEAD; use hotshot_task::{boxed_sync, BoxSyncFuture}; use hotshot_types::{ data::ViewNumber, @@ -82,7 +82,7 @@ struct Libp2pNetworkInner { /// this node's public key pk: K, /// handle to control the network - handle: Arc>, + handle: Arc>, /// map of known replica peer ids to public keys broadcast_recv: UnboundedReceiver, /// Sender for broadcast messages @@ -93,8 +93,6 @@ struct Libp2pNetworkInner { direct_recv: UnboundedReceiver, /// Sender for node lookup (relevant view number, key of node) (None for shutdown) node_lookup_send: UnboundedSender>, - /// Sender for shutdown of the peer cache's garbage collection task - cache_gc_shutdown_send: UnboundedSender<()>, /// this is really cheating to enable local tests /// hashset of (bootstrap_addr, peer_id) bootstrap_addrs: PeerInfoVec, @@ -200,6 +198,8 @@ where // setting to sane defaults .ttl(None) .republication_interval(None) + // this removes the cache for tests + .dht_cache_location(None) .build() .unwrap() } else { @@ -220,6 +220,8 @@ where // setting to sane defaults .ttl(None) .republication_interval(None) + // this removes the cache for tests + .dht_cache_location(None) .build() .unwrap() }; @@ -287,7 +289,7 @@ impl Libp2pNetwork { ) -> Result, NetworkError> { assert!(bootstrap_addrs_len > 4, "Need at least 5 bootstrap nodes"); let network_handle = Arc::new( - NetworkNodeHandle::<(), K>::new(config, id) + Box::pin(NetworkNodeHandle::<()>::new(config, id)) .await .map_err(Into::::into)?, ); @@ -318,7 +320,6 @@ impl Libp2pNetwork { let (direct_send, direct_recv) = unbounded(); let (broadcast_send, broadcast_recv) = unbounded(); let (node_lookup_send, node_lookup_recv) = unbounded(); - let (cache_gc_shutdown_send, cache_gc_shutdown_recv) = unbounded::<()>(); let result = Libp2pNetwork { inner: Arc::new(Libp2pNetworkInner { @@ -336,7 +337,6 @@ impl Libp2pNetwork { metrics: NetworkingMetrics::new(&*metrics), topic_map, node_lookup_send, - cache_gc_shutdown_send, // Start the latest view from 0. "Latest" refers to "most recent view we are polling for // proposals on". We need this because to have consensus info injected we need a working // network already. In the worst case, we send a few lookups we don't need. @@ -345,20 +345,15 @@ impl Libp2pNetwork { }; result.spawn_event_generator(direct_send, broadcast_send); - result.spawn_node_lookup(node_lookup_recv, cache_gc_shutdown_recv); + result.spawn_node_lookup(node_lookup_recv); result.spawn_connect(id); Ok(result) } /// Spawns task for looking up nodes pre-emptively - /// as well as garbage collecting the peer cache #[allow(clippy::cast_sign_loss, clippy::cast_precision_loss)] - fn spawn_node_lookup( - &self, - node_lookup_recv: UnboundedReceiver>, - cache_gc_shutdown_send: UnboundedReceiver<()>, - ) { + fn spawn_node_lookup(&self, node_lookup_recv: UnboundedReceiver>) { let handle = self.inner.handle.clone(); let dht_timeout = self.inner.dht_timeout; let latest_seen_view = self.inner.latest_seen_view.clone(); @@ -375,32 +370,13 @@ impl Libp2pNetwork { // only run if we are not too close to the next view number if latest_seen_view.load(Ordering::Relaxed) + THRESHOLD <= *view_number { - // look up node, caching if applicable + // look up if let Err(err) = handle_.lookup_node::(pk.clone(), dht_timeout).await { error!("Failed to perform lookup for key {:?}: {}", pk, err); }; } } }); - - // deals with garbage collecting the lookup queue - let handle_ = handle.clone(); - async_spawn(async move { - loop { - let ttl = handle_ - .config() - .ttl - .unwrap_or(Duration::from_secs(KAD_DEFAULT_REPUB_INTERVAL_SEC * 8)); - if async_timeout(ttl, cache_gc_shutdown_send.recv()) - .await - .is_err() - { - handle_.prune_peer_cache().await; - } else { - break; - } - } - }); } /// Initiates connection to the outside world @@ -573,7 +549,6 @@ impl ConnectedNetwork for Libp2p { let closure = async move { self.inner.node_lookup_send.send(None).await.unwrap(); - self.inner.cache_gc_shutdown_send.send(()).await.unwrap(); if self.inner.handle.is_killed() { error!("Called shut down when already shut down! Noop."); } else { diff --git a/crates/libp2p-networking/src/network/behaviours/dht/cache.rs b/crates/libp2p-networking/src/network/behaviours/dht/cache.rs new file mode 100644 index 0000000000..602bb41e16 --- /dev/null +++ b/crates/libp2p-networking/src/network/behaviours/dht/cache.rs @@ -0,0 +1,325 @@ +use std::{ + collections::{BTreeMap, HashMap}, + sync::{ + atomic::{AtomicU32, Ordering}, + Arc, + }, + time::{Duration, SystemTime}, +}; + +use async_compatibility_layer::art::async_block_on; +use async_lock::RwLock; +use bincode::Options; +use dashmap::{mapref::one::Ref, DashMap}; +use hotshot_constants::KAD_DEFAULT_REPUB_INTERVAL_SEC; +use hotshot_utils::bincode::bincode_opts; +use snafu::{ResultExt, Snafu}; + +/// Error wrapper type for cache +#[derive(Debug, Snafu)] +#[snafu(visibility(pub))] +pub enum CacheError { + /// Failed to read or write from disk + Disk { + /// source of error + source: std::io::Error, + }, + + /// Failure to serialize the cache + Serialization { + /// source of error + source: Box, + }, + + /// Failure to deserialize the cache + Deserialization { + /// source of error + source: Box, + }, + + /// General cache error + GeneralCache { + /// source of error + source: Box, + }, +} + +#[derive(Clone, derive_builder::Builder, custom_debug::Debug, Default)] +pub struct Config { + #[builder(default = "Some(\"dht.cache\".to_string())")] + pub filename: Option, + #[builder(default = "Duration::from_secs(KAD_DEFAULT_REPUB_INTERVAL_SEC * 16)")] + pub expiry: Duration, + #[builder(default = "4")] + pub max_disk_parity_delta: u32, +} + +impl Default for Cache { + fn default() -> Self { + async_block_on(Self::new(Config::default())) + } +} + +pub struct Cache { + /// the cache's config + config: Config, + + /// the cache for records (key -> value) + cache: Arc, Vec>>, + /// the expiries for the dht cache, in order (expiry time -> key) + expiries: Arc>>>, + + /// number of inserts since the last save + disk_parity_delta: Arc, +} + +impl Cache { + pub async fn new(config: Config) -> Self { + let cache = Self { + cache: Arc::new(DashMap::new()), + expiries: Arc::new(RwLock::new(BTreeMap::new())), + config, + disk_parity_delta: Arc::new(AtomicU32::new(0)), + }; + + // try loading from file + if let Err(err) = cache.load().await { + tracing::warn!("failed to load cache from file: {}", err); + }; + + cache + } + + pub async fn load(&self) -> Result<(), CacheError> { + if let Some(filename) = &self.config.filename { + let encoded = std::fs::read(filename).context(DiskSnafu)?; + + let cache: HashMap, Vec)> = bincode_opts() + .deserialize(&encoded) + .context(DeserializationSnafu)?; + + // inline prune and insert + let now = SystemTime::now(); + for (expiry, (key, value)) in cache { + if now < expiry { + self.cache.insert(key.clone(), value); + self.expiries.write().await.insert(expiry, key); + } + } + } + + Ok(()) + } + + pub async fn save(&self) -> Result<(), CacheError> { + if let Some(filename) = &self.config.filename { + // prune first + self.prune().await; + + // serialize + let mut cache_to_write = HashMap::new(); + let expiries = self.expiries.read().await; + for (expiry, key) in &*expiries { + if let Some(entry) = self.cache.get(key) { + cache_to_write.insert(expiry, (key, entry.value().clone())); + } else { + tracing::warn!("key not found in cache: {:?}", key); + Err(CacheError::GeneralCache { + source: Box::new(bincode::ErrorKind::Custom( + "key not found in cache".to_string(), + )), + })?; + }; + } + + let encoded = bincode_opts() + .serialize(&cache_to_write) + .context(SerializationSnafu)?; + + std::fs::write(filename, encoded).context(DiskSnafu)?; + } + + Ok(()) + } + + async fn prune(&self) { + let now = SystemTime::now(); + let mut expiries = self.expiries.write().await; + let mut removed: u32 = 0; + + while let Some((expires, key)) = expiries.pop_first() { + if now > expires { + self.cache.remove(&key); + removed += 1; + } else { + expiries.insert(expires, key); + break; + } + } + + if removed > 0 { + self.disk_parity_delta.fetch_add(removed, Ordering::Relaxed); + } + } + + pub async fn get(&self, key: &Vec) -> Option, Vec>> { + // prune, save if necessary + self.prune().await; + self.save_if_necessary().await; + + // get + self.cache.get(key) + } + + pub async fn insert(&self, key: Vec, value: Vec) { + // insert into cache and expiries + self.cache.insert(key.clone(), value); + self.expiries + .write() + .await + .insert(SystemTime::now() + self.config.expiry, key); + + // save if reached max disk parity delta + self.disk_parity_delta.fetch_add(1, Ordering::Relaxed); + self.save_if_necessary().await; + } + + async fn save_if_necessary(&self) { + let cur_disk_parity_delta = self.disk_parity_delta.load(Ordering::Relaxed); + if cur_disk_parity_delta >= self.config.max_disk_parity_delta { + if let Err(err) = self.save().await { + tracing::error!("failed to save cache to file: {}", err); + }; + } + } +} + +#[cfg(test)] +mod test { + + use super::*; + use async_compatibility_layer::art::async_sleep; + use libp2p_identity::PeerId; + use tracing::instrument; + + /// cache eviction test + #[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) + )] + #[cfg_attr(async_executor_impl = "async-std", async_std::test)] + #[instrument] + async fn test_dht_cache_eviction() { + async_compatibility_layer::logging::setup_logging(); + async_compatibility_layer::logging::setup_backtrace(); + + // cache with 1s eviction + let cache = Cache::new(Config { + filename: None, + expiry: Duration::from_secs(1), + max_disk_parity_delta: 4, + }) + .await; + + let (key, value) = (PeerId::random(), PeerId::random()); + + // insert + cache.insert(key.to_bytes(), value.to_bytes()).await; + + // check that it is in the cache and expiries + assert_eq!( + cache.get(&key.to_bytes()).await.unwrap().value(), + &value.to_bytes() + ); + assert_eq!(cache.expiries.read().await.len(), 1); + + // sleep for 1s + async_sleep(Duration::from_secs(1)).await; + + // check that now is evicted + assert!(cache.get(&key.to_bytes()).await.is_none()); + + // check that the cache and expiries are empty + assert!(cache.expiries.read().await.is_empty()); + assert!(cache.cache.is_empty()); + } + + /// cache add test + #[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) + )] + #[cfg_attr(async_executor_impl = "async-std", async_std::test)] + #[instrument] + async fn test_dht_cache_save_load() { + let _ = std::fs::remove_file("test.cache"); + + let cache = Cache::new(Config { + filename: Some("test.cache".to_string()), + expiry: Duration::from_secs(600), + max_disk_parity_delta: 4, + }) + .await; + + // add 10 key-value pairs to the cache + for i in 0u8..10u8 { + let (key, value) = (vec![i; 1], vec![i + 1; 1]); + cache.insert(key, value).await; + } + + // save the cache + cache.save().await.unwrap(); + + // load the cache + let cache = Cache::new(Config { + filename: Some("test.cache".to_string()), + expiry: Duration::from_secs(600), + max_disk_parity_delta: 4, + }) + .await; + + // check that the cache has the 10 key-value pairs + for i in 0u8..10u8 { + let (key, value) = (vec![i; 1], vec![i + 1; 1]); + assert_eq!(cache.get(&key).await.unwrap().value(), &value); + } + + // delete the cache file + let _ = std::fs::remove_file("test.cache"); + } + + #[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) + )] + #[cfg_attr(async_executor_impl = "async-std", async_std::test)] + #[instrument] + async fn test_dht_disk_parity() { + let _ = std::fs::remove_file("test.cache"); + + let cache = Cache::new(Config { + // tests run sequentially, shouldn't matter + filename: Some("test.cache".to_string()), + expiry: Duration::from_secs(600), + max_disk_parity_delta: 4, + }) + .await; + + // insert into cache + for i in 0..3 { + cache.insert(vec![i; 1], vec![i + 1; 1]).await; + } + + // check that file is not saved + assert!(!std::path::Path::new("test.cache").exists()); + + // insert into cache + cache.insert(vec![0; 1], vec![1; 1]).await; + + // check that file is saved + assert!(std::path::Path::new("test.cache").exists()); + + // delete the cache file + _ = std::fs::remove_file("test.cache"); + } +} diff --git a/crates/libp2p-networking/src/network/behaviours/dht.rs b/crates/libp2p-networking/src/network/behaviours/dht/mod.rs similarity index 94% rename from crates/libp2p-networking/src/network/behaviours/dht.rs rename to crates/libp2p-networking/src/network/behaviours/dht/mod.rs index 46adb05d0c..7086b6dab1 100644 --- a/crates/libp2p-networking/src/network/behaviours/dht.rs +++ b/crates/libp2p-networking/src/network/behaviours/dht/mod.rs @@ -5,6 +5,9 @@ use std::{ time::Duration, }; +mod cache; + +use async_compatibility_layer::art::async_block_on; use futures::channel::oneshot::Sender; use libp2p::{ kad::{ @@ -21,6 +24,8 @@ use tracing::{error, info, warn}; pub(crate) const NUM_REPLICATED_TO_TRUST: usize = 2; const MAX_DHT_QUERY_SIZE: usize = 5; +use self::cache::Cache; + use super::exponential_backoff::ExponentialBackoff; /// Behaviour wrapping libp2p's kademlia @@ -56,6 +61,8 @@ pub struct DHTBehaviour { pub peer_id: PeerId, /// replication factor pub replication_factor: NonZeroUsize, + /// kademlia cache + cache: Cache, } /// State of bootstrapping @@ -106,10 +113,11 @@ impl DHTBehaviour { /// Create a new DHT behaviour #[must_use] - pub fn new( + pub async fn new( mut kadem: Kademlia, pid: PeerId, replication_factor: NonZeroUsize, + cache_location: Option, ) -> Self { // needed because otherwise we stay in client mode when testing locally // and don't publish keys stuff @@ -138,6 +146,13 @@ impl DHTBehaviour { }, in_progress_get_closest_peers: HashMap::default(), replication_factor, + cache: Cache::new( + cache::ConfigBuilder::default() + .filename(cache_location) + .build() + .unwrap_or_default(), + ) + .await, } } @@ -223,17 +238,26 @@ impl DHTBehaviour { return; } - let qid = self.kadem.get_record(key.clone().into()); - let query = KadGetQuery { - backoff, - progress: DHTProgress::InProgress(qid), - notify: chan, - num_replicas: factor, - key, - retry_count: retry_count - 1, - records: HashMap::default(), - }; - self.in_progress_get_record_queries.insert(qid, query); + // check cache before making the request + if let Some(entry) = async_block_on(self.cache.get(&key)) { + // exists in cache + if chan.send(entry.value().clone()).is_err() { + warn!("Get DHT: channel closed before get record request result could be sent"); + } + } else { + // doesn't exist in cache, actually propagate request + let qid = self.kadem.get_record(key.clone().into()); + let query = KadGetQuery { + backoff, + progress: DHTProgress::InProgress(qid), + notify: chan, + num_replicas: factor, + key, + retry_count: retry_count - 1, + records: HashMap::default(), + }; + self.in_progress_get_record_queries.insert(qid, query); + } } /// update state based on recv-ed get query @@ -279,6 +303,10 @@ impl DHTBehaviour { .into_iter() .find(|(_, v)| *v >= NUM_REPLICATED_TO_TRUST) { + // insert into cache + async_block_on(self.cache.insert(key, r.clone())); + + // return value if notify.send(r).is_err() { warn!("Get DHT: channel closed before get record request result could be sent"); } diff --git a/crates/libp2p-networking/src/network/mod.rs b/crates/libp2p-networking/src/network/mod.rs index 54b3d89035..3ec1c07b73 100644 --- a/crates/libp2p-networking/src/network/mod.rs +++ b/crates/libp2p-networking/src/network/mod.rs @@ -34,7 +34,7 @@ use libp2p::{ use libp2p_identity::PeerId; use rand::seq::IteratorRandom; use serde::{Deserialize, Serialize}; -use std::{collections::HashSet, fmt::Debug, hash::Hash, str::FromStr, sync::Arc, time::Duration}; +use std::{collections::HashSet, fmt::Debug, str::FromStr, sync::Arc, time::Duration}; use tracing::{info, instrument}; #[cfg(async_executor_impl = "async-std")] @@ -229,12 +229,12 @@ pub async fn gen_transport( /// a single node, connects them to each other /// and waits for connections to propagate to all nodes. #[instrument] -pub async fn spin_up_swarm( +pub async fn spin_up_swarm( timeout_len: Duration, known_nodes: Vec<(Option, Multiaddr)>, config: NetworkNodeConfig, idx: usize, - handle: &Arc>, + handle: &Arc>, ) -> Result<(), NetworkNodeHandleError> { info!("known_nodes{:?}", known_nodes); handle.add_known_peers(known_nodes).await?; @@ -248,9 +248,9 @@ pub async fn spin_up_swarm( - handles: &[Arc>], +pub fn get_random_handle( + handles: &[Arc>], rng: &mut dyn rand::RngCore, -) -> Arc> { +) -> Arc> { handles.iter().choose(rng).unwrap().clone() } diff --git a/crates/libp2p-networking/src/network/node.rs b/crates/libp2p-networking/src/network/node.rs index 2f7dd46ba4..835058bf84 100644 --- a/crates/libp2p-networking/src/network/node.rs +++ b/crates/libp2p-networking/src/network/node.rs @@ -269,7 +269,9 @@ impl NetworkNode { config .replication_factor .unwrap_or_else(|| NonZeroUsize::new(4).unwrap()), - ), + config.dht_cache_location.clone(), + ) + .await, identify, DMBehaviour::new(request_response), ); diff --git a/crates/libp2p-networking/src/network/node/config.rs b/crates/libp2p-networking/src/network/node/config.rs index 4d19b6f516..82897c0de5 100644 --- a/crates/libp2p-networking/src/network/node/config.rs +++ b/crates/libp2p-networking/src/network/node/config.rs @@ -24,6 +24,11 @@ pub struct NetworkNodeConfig { #[builder(setter(into, strip_option), default = "DEFAULT_REPLICATION_FACTOR")] pub replication_factor: Option, + /// location of the dht cache + /// default is "dht.cache" in the current directory + #[builder(default = "Some(\"dht.cache\".to_string())")] + pub dht_cache_location: Option, + #[builder(default)] /// parameters for gossipsub mesh network pub mesh_params: Option, diff --git a/crates/libp2p-networking/src/network/node/handle.rs b/crates/libp2p-networking/src/network/node/handle.rs index 04961140c6..c4e6460666 100644 --- a/crates/libp2p-networking/src/network/node/handle.rs +++ b/crates/libp2p-networking/src/network/node/handle.rs @@ -11,25 +11,22 @@ use async_compatibility_layer::{ UnboundedReceiver, UnboundedRecvError, UnboundedSender, }, }; -use async_lock::{Mutex, RwLock}; +use async_lock::Mutex; use bincode::Options; -use dashmap::DashMap; use futures::{stream::FuturesOrdered, Future, FutureExt}; -use hotshot_constants::KAD_DEFAULT_REPUB_INTERVAL_SEC; use hotshot_utils::bincode::bincode_opts; use libp2p::{request_response::ResponseChannel, Multiaddr}; use libp2p_identity::PeerId; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; use std::{ - collections::{BTreeMap, HashSet}, + collections::HashSet, fmt::Debug, - hash::Hash, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, - time::{Duration, Instant, SystemTime}, + time::{Duration, Instant}, }; use tracing::{debug, info, instrument}; @@ -37,7 +34,7 @@ use tracing::{debug, info, instrument}; /// - A reference to the state /// - Controls for the swarm #[derive(Debug)] -pub struct NetworkNodeHandle { +pub struct NetworkNodeHandle { /// network configuration network_config: NetworkNodeConfig, /// the state of the replica @@ -51,10 +48,6 @@ pub struct NetworkNodeHandle { peer_id: PeerId, /// human readable id id: usize, - /// the cache for peers we've looked up - peer_cache: Arc>, - /// the expiries for the peer cache, in order - peer_cache_expiries: Arc>>, /// A list of webui listeners that are listening for changes on this node webui_listeners: Arc>>>, @@ -91,7 +84,7 @@ impl NetworkNodeReceiver { } } -impl NetworkNodeHandle { +impl NetworkNodeHandle { /// constructs a new node listening on `known_addr` #[instrument] pub async fn new(config: NetworkNodeConfig, id: usize) -> Result { @@ -126,8 +119,6 @@ impl NetworkNodeHa listen_addr, peer_id, id, - peer_cache: Arc::new(DashMap::new()), - peer_cache_expiries: Arc::new(RwLock::new(BTreeMap::new())), webui_listeners: Arc::default(), receiver: NetworkNodeReceiver { kill_switch, @@ -147,10 +138,9 @@ impl NetworkNodeHa #[allow(clippy::unused_async)] pub async fn spawn_handler(self: &Arc, cb: F) -> impl Future where - F: Fn(NetworkEvent, Arc>) -> RET + Sync + Send + 'static, + F: Fn(NetworkEvent, Arc>) -> RET + Sync + Send + 'static, RET: Future> + Send + 'static, S: Send + 'static, - K: Send + Sync + 'static, { assert!( !self.receiver.receiver_spawned.swap(true, Ordering::Relaxed), @@ -269,7 +259,7 @@ impl NetworkNodeHa } } -impl NetworkNodeHandle { +impl NetworkNodeHandle { /// Print out the routing table used by kademlia /// NOTE: only for debugging purposes currently /// # Errors @@ -292,48 +282,16 @@ impl NetworkNodeHandle { r.await.map_err(|_| NetworkNodeHandleError::RecvError) } - /// Prunes the peer lookup cache, removing old entries - /// Should be 1:1 with kademlia expiries - pub async fn prune_peer_cache(&self) { - let now = SystemTime::now(); - let mut expiries = self.peer_cache_expiries.write().await; - - while let Some((expires, key)) = expiries.pop_first() { - if now > expires { - self.peer_cache.remove(&key); - } else { - expiries.insert(expires, key); - break; - } - } - } - /// Looks up a node's `PeerId` and attempts to validate routing - /// Will use cached `PeerId` if available /// # Errors /// if the peer was unable to be looked up (did not provide a response, DNE) - pub async fn lookup_node Deserialize<'a>>( + pub async fn lookup_node Deserialize<'a> + Serialize>( &self, - key: K, + key: V, dht_timeout: Duration, ) -> Result { - let pid = if let Some(record) = self.peer_cache.get(&key) { - // exists in cache. look up routing but skip kademlia - *record.value() - } else { - // does not exist in cache. look up in kademlia, store in cache - let pid = self.get_record_timeout::(&key, dht_timeout).await?; - self.peer_cache.insert(key.clone(), pid); - self.peer_cache_expiries.write().await.insert( - SystemTime::now() - + self - .network_config - .ttl - .unwrap_or(Duration::from_secs(KAD_DEFAULT_REPUB_INTERVAL_SEC * 16)), - key, - ); - pid - }; + // get record (from DHT) + let pid = self.get_record_timeout::(&key, dht_timeout).await?; // pid lookup for routing self.lookup_pid(pid).await?; @@ -669,7 +627,7 @@ impl NetworkNodeHandle { } } -impl NetworkNodeHandle { +impl NetworkNodeHandle { /// Get a clone of the internal state pub async fn state(&self) -> S { self.state.cloned().await @@ -738,106 +696,3 @@ pub mod network_node_handle_error { NetworkSnafu, NodeConfigSnafu, RecvSnafu, SendSnafu, SerializationSnafu, TimeoutSnafu, }; } - -#[cfg(test)] -mod test { - use super::*; - - /// libp2p peer cache test - #[cfg_attr( - async_executor_impl = "tokio", - tokio::test(flavor = "multi_thread", worker_threads = 2) - )] - #[cfg_attr(async_executor_impl = "async-std", async_std::test)] - #[instrument] - async fn test_libp2p_cache_eviction() { - async_compatibility_layer::logging::setup_logging(); - async_compatibility_layer::logging::setup_backtrace(); - - let handle: NetworkNodeHandle<(), PeerId> = - NetworkNodeHandle::new(NetworkNodeConfig::default(), 0) - .await - .unwrap(); - - let now = SystemTime::now(); - let later = now + Duration::from_secs(1); - - // present insert - let present_key = PeerId::random(); - let present_pid = PeerId::random(); - handle.peer_cache.insert(present_key, present_pid); - handle - .peer_cache_expiries - .write() - .await - .insert(now, present_key); - - // later insert - let later_key = PeerId::random(); - let later_pid = PeerId::random(); - handle.peer_cache.insert(later_key, later_pid); - handle - .peer_cache_expiries - .write() - .await - .insert(now + Duration::from_secs(1), later_key); - - // check that now and later exist - assert!(handle - .peer_cache - .get(&present_key) - .is_some_and(|entry| entry.value() == &present_pid)); - assert!(handle - .peer_cache - .get(&later_key) - .is_some_and(|entry| entry.value() == &later_pid)); - assert!(handle - .peer_cache_expiries - .read() - .await - .get(&now) - .is_some_and(|entry| entry == &present_key)); - assert!(handle - .peer_cache_expiries - .read() - .await - .get(&later) - .is_some_and(|entry| entry == &later_key)); - - // prune - handle.prune_peer_cache().await; - - // check that now doesn't exist and later does - assert!(handle.peer_cache.get(&present_key).is_none()); - assert!(handle - .peer_cache - .get(&later_key) - .is_some_and(|entry| entry.value() == &later_pid)); - assert!(handle.peer_cache_expiries.read().await.get(&now).is_none()); - assert!(handle - .peer_cache_expiries - .read() - .await - .get(&later) - .is_some_and(|entry| entry == &later_key)); - - // wait for later to expire - async_sleep(Duration::from_secs(1)).await; - - // prune - handle.prune_peer_cache().await; - - // check that later doesn't exist - assert!(handle.peer_cache.get(&later_key).is_none()); - assert!(handle - .peer_cache_expiries - .read() - .await - .get(&later) - .is_none()); - - // check that the expiries and cache are empty - assert!(handle.peer_cache_expiries.read().await.is_empty()); - assert!(handle.peer_cache.is_empty()); - } -} diff --git a/crates/libp2p-networking/tests/common/mod.rs b/crates/libp2p-networking/tests/common/mod.rs index 5a531bbafb..ca9e967319 100644 --- a/crates/libp2p-networking/tests/common/mod.rs +++ b/crates/libp2p-networking/tests/common/mod.rs @@ -39,8 +39,8 @@ pub async fn test_bed, FutG: Future> + 'static + Send + Sync, - F: FnOnce(Vec>>, Duration) -> FutF, - G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, + F: FnOnce(Vec>>, Duration) -> FutF, + G: Fn(NetworkEvent, Arc>) -> FutG + 'static + Send + Sync, { setup_logging(); setup_backtrace(); @@ -69,7 +69,7 @@ pub async fn test_bed(handles: &[Arc>]) -> HashMap { +fn gen_peerid_map(handles: &[Arc>]) -> HashMap { let mut r_val = HashMap::new(); for handle in handles { r_val.insert(handle.peer_id(), handle.id()); @@ -79,7 +79,7 @@ fn gen_peerid_map(handles: &[Arc>]) -> HashMap(handles: &[Arc>]) { +pub async fn print_connections(handles: &[Arc>]) { let m = gen_peerid_map(handles); warn!("PRINTING CONNECTION STATES"); for handle in handles.iter() { @@ -104,7 +104,7 @@ pub async fn spin_up_swarms( num_of_nodes: usize, timeout_len: Duration, num_bootstrap: usize, -) -> Result>>, TestError> { +) -> Result>>, TestError> { let mut handles = Vec::new(); let mut bootstrap_addrs = Vec::<(PeerId, Multiaddr)>::new(); let mut connecting_futs = Vec::new(); diff --git a/crates/libp2p-networking/tests/counter.rs b/crates/libp2p-networking/tests/counter.rs index 85b7cb2a7f..eefbdcf37b 100644 --- a/crates/libp2p-networking/tests/counter.rs +++ b/crates/libp2p-networking/tests/counter.rs @@ -56,7 +56,7 @@ pub enum CounterMessage { #[instrument] pub async fn counter_handle_network_event( event: NetworkEvent, - handle: Arc>, + handle: Arc>, ) -> Result<(), NetworkNodeHandleError> { use CounterMessage::*; use NetworkEvent::*; @@ -121,8 +121,8 @@ pub async fn counter_handle_network_event( /// `requester_handle` asks for `requestee_handle`'s state, /// and then `requester_handle` updates its state to equal `requestee_handle`. async fn run_request_response_increment<'a>( - requester_handle: Arc>, - requestee_handle: Arc>, + requester_handle: Arc>, + requestee_handle: Arc>, timeout: Duration, ) -> Result<(), TestError> { async move { @@ -168,7 +168,7 @@ async fn run_request_response_increment<'a>( /// broadcasts `msg` from a randomly chosen handle /// then asserts that all nodes match `new_state` async fn run_gossip_round( - handles: &[Arc>], + handles: &[Arc>], msg: CounterMessage, new_state: CounterState, timeout_duration: Duration, @@ -234,7 +234,7 @@ async fn run_gossip_round( } async fn run_intersperse_many_rounds( - handles: Vec>>, + handles: Vec>>, timeout: Duration, ) { for i in 0..NUM_ROUNDS as u32 { @@ -250,21 +250,18 @@ async fn run_intersperse_many_rounds( } async fn run_dht_many_rounds( - handles: Vec>>, + handles: Vec>>, timeout: Duration, ) { run_dht_rounds(&handles, timeout, 0, NUM_ROUNDS).await; } -async fn run_dht_one_round( - handles: Vec>>, - timeout: Duration, -) { +async fn run_dht_one_round(handles: Vec>>, timeout: Duration) { run_dht_rounds(&handles, timeout, 0, 1).await; } async fn run_request_response_many_rounds( - handles: Vec>>, + handles: Vec>>, timeout: Duration, ) { for _i in 0..NUM_ROUNDS { @@ -276,7 +273,7 @@ async fn run_request_response_many_rounds( } pub async fn run_request_response_one_round( - handles: Vec>>, + handles: Vec>>, timeout: Duration, ) { run_request_response_increment_all(&handles, timeout).await; @@ -286,21 +283,21 @@ pub async fn run_request_response_one_round( } pub async fn run_gossip_many_rounds( - handles: Vec>>, + handles: Vec>>, timeout: Duration, ) { run_gossip_rounds(&handles, NUM_ROUNDS, 0, timeout).await } async fn run_gossip_one_round( - handles: Vec>>, + handles: Vec>>, timeout: Duration, ) { run_gossip_rounds(&handles, 1, 0, timeout).await } async fn run_dht_rounds( - handles: &[Arc>], + handles: &[Arc>], timeout: Duration, starting_val: usize, num_rounds: usize, @@ -336,7 +333,7 @@ async fn run_dht_rounds( /// runs `num_rounds` of message broadcast, incrementing the state of all nodes each broadcast async fn run_gossip_rounds( - handles: &[Arc>], + handles: &[Arc>], num_rounds: usize, starting_state: CounterState, timeout: Duration, @@ -361,7 +358,7 @@ async fn run_gossip_rounds( /// then has all other peers request its state /// and update their state to the recv'ed state async fn run_request_response_increment_all( - handles: &[Arc>], + handles: &[Arc>], timeout: Duration, ) { let mut rng = rand::thread_rng(); From 2d51285e4f05033f0e156823310d8dba95622a26 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Mon, 25 Sep 2023 18:05:32 -0700 Subject: [PATCH 19/37] Address PR comments --- crates/hotshot/src/demo.rs | 7 ++++-- crates/task-impls/src/transactions.rs | 16 ++++++++++--- crates/testing/tests/da_task.rs | 6 ++++- crates/testing/tests/network_task.rs | 5 +++- crates/types/src/block_impl.rs | 29 ++++++++--------------- crates/types/src/traits/block_contents.rs | 14 +++++------ 6 files changed, 44 insertions(+), 33 deletions(-) diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index 468ff5e420..cec7120acd 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -101,9 +101,12 @@ impl TestableState for SDemoState { fn create_random_transaction( _state: Option<&Self>, _rng: &mut dyn rand::RngCore, - _padding: u64, + padding: u64, ) -> ::Transaction { - VIDTransaction(vec![0]) + if padding == 0 { + panic!("Padding should be nonzero for VID computation to work."); + } + VIDTransaction(vec![0; padding as usize]) } } /// Implementation of [`NodeType`] for [`VDemoNode`] diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 11475fdbcf..a9c8f9ad52 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -21,7 +21,6 @@ use hotshot_types::{ data::{SequencingLeaf, VidDisperse, VidScheme, VidSchemeTrait}, message::{Message, Proposal, SequencingMessage}, traits::{ - block_contents::Transaction, consensus_api::SequencingConsensusApi, election::{CommitteeExchangeType, ConsensusExchange}, node_implementation::{CommitteeEx, NodeImplementation, NodeType}, @@ -88,6 +87,9 @@ pub struct TransactionTaskState< pub id: u64, } +// We have two `TransactionTaskState` implementations with different bounds. The implementation +// here requires `TYPES: NodeType`, +// whereas it's just `TYPES: NodeType` in the second implementation. impl< TYPES: NodeType, I: NodeImplementation< @@ -245,15 +247,20 @@ where // TODO https://github.com/EspressoSystems/jellyfish/issues/375 let mut txns_flatten = Vec::new(); for txn in &txns { - txns_flatten.extend(txn.bytes()); + txns_flatten.extend(txn.0.clone()); } let vid_disperse = vid.disperse(&txns_flatten).unwrap(); - let block = VIDBlockPayload::new(txns, vid_disperse.commit); + let block = VIDBlockPayload { + transactions: txns, + commitment: vid_disperse.commit, + }; self.event_stream .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) .await; + // TODO (Keyao) Determine and update where to publish VidDisperseSend. + // self.event_stream .publish(SequencingHotShotEvent::VidDisperseSend( Proposal { @@ -284,6 +291,9 @@ where } } +// We have two `TransactionTaskState` implementations with different bounds. The implementation +// above requires `TYPES: NodeType`, +// whereas here it's just `TYPES: NodeType`. impl< TYPES: NodeType, I: NodeImplementation< diff --git a/crates/testing/tests/da_task.rs b/crates/testing/tests/da_task.rs index f1b1744884..e31c34e6aa 100644 --- a/crates/testing/tests/da_task.rs +++ b/crates/testing/tests/da_task.rs @@ -43,7 +43,11 @@ async fn test_da_task() { let txn = vec![0u8]; let vid_disperse = vid.disperse(&txn).unwrap(); let block_commitment = vid_disperse.commit; - let block = VIDBlockPayload::new(vec![VIDTransaction(txn)], block_commitment); + let block = VIDBlockPayload { + transactions: vec![VIDTransaction(txn)], + commitment: block_commitment, + }; + let signature = committee_exchange.sign_da_proposal(&block.commit()); let proposal = DAProposal { deltas: block.clone(), diff --git a/crates/testing/tests/network_task.rs b/crates/testing/tests/network_task.rs index 3413bc4898..c4165a8c31 100644 --- a/crates/testing/tests/network_task.rs +++ b/crates/testing/tests/network_task.rs @@ -46,7 +46,10 @@ async fn test_network_task() { let txn = vec![0u8]; let vid_disperse = vid.disperse(&txn).unwrap(); let block_commitment = vid_disperse.commit; - let block = VIDBlockPayload::new(vec![VIDTransaction(txn)], block_commitment); + let block = VIDBlockPayload { + transactions: vec![VIDTransaction(txn)], + commitment: block_commitment, + }; let signature = committee_exchange.sign_da_proposal(&block.commit()); let da_proposal = Proposal { data: DAProposal { diff --git a/crates/types/src/block_impl.rs b/crates/types/src/block_impl.rs index 03a9ca3737..2360cb3a24 100644 --- a/crates/types/src/block_impl.rs +++ b/crates/types/src/block_impl.rs @@ -38,11 +38,7 @@ impl Committable for VIDTransaction { } } -impl Transaction for VIDTransaction { - fn bytes(&self) -> Vec { - self.0.clone() - } -} +impl Transaction for VIDTransaction {} /// The error type for block payload. #[derive(Snafu, Debug)] @@ -69,29 +65,24 @@ pub struct VIDBlockPayload { } impl VIDBlockPayload { - /// Constructor. - #[must_use] - pub fn new( - transactions: Vec, - commitment: ::Commit, - ) -> Self { - Self { - transactions, - commitment, - } - } - - /// Create a genesis block payload with transaction bytes `vec![0]`. + /// Create a genesis block payload with transaction bytes `vec![0]`, to be used for + /// consensus task initiation. /// # Panics /// If the `VidScheme` construction fails. #[must_use] pub fn genesis() -> Self { // TODO let srs = test_srs(NUM_STORAGE_NODES); + // TODO We are using constant numbers for now, but they will change as the quorum size + // changes. + // TODO let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); let txn = vec![0]; let vid_disperse = vid.disperse(&txn).unwrap(); - VIDBlockPayload::new(vec![VIDTransaction(txn)], vid_disperse.commit) + VIDBlockPayload { + transactions: vec![VIDTransaction(txn)], + commitment: vid_disperse.commit, + } } } diff --git a/crates/types/src/traits/block_contents.rs b/crates/types/src/traits/block_contents.rs index 4ba10f601c..2fc3383a14 100644 --- a/crates/types/src/traits/block_contents.rs +++ b/crates/types/src/traits/block_contents.rs @@ -13,6 +13,8 @@ use std::{ hash::Hash, }; +// TODO (Keyao) Determine whether we can refactor BlockPayload and Transaction from traits to structs. +// /// Abstraction over the full contents of a block /// /// This trait encapsulates the behaviors that the transactions of a block must have in order to be @@ -45,12 +47,12 @@ pub trait BlockPayload: fn contained_transactions(&self) -> HashSet>; } +// TODO (Keyao) Determine whether we can refactor BlockPayload and Transaction from traits to structs. +// /// Abstraction over any type of transaction. Used by [`BlockPayload`]. pub trait Transaction: Clone + Serialize + DeserializeOwned + Debug + PartialEq + Eq + Sync + Send + Committable + Hash { - /// Get the transaction bytes. - fn bytes(&self) -> Vec; } /// Dummy implementation of `BlockPayload` for unit tests @@ -64,6 +66,8 @@ pub mod dummy { pub use crate::traits::state::dummy::DummyState; use crate::traits::state::TestableBlock; + // TODO (Keyao) Investigate the use of DummyBlock. + // /// The dummy block #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub struct DummyBlock { @@ -100,11 +104,7 @@ pub mod dummy { "DUMMY_TXN".to_string() } } - impl super::Transaction for DummyTransaction { - fn bytes(&self) -> Vec { - Vec::new() - } - } + impl super::Transaction for DummyTransaction {} impl std::error::Error for DummyError {} From c3310380fc11abe0dfd57458108f702d3fc32f82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 06:56:26 -0400 Subject: [PATCH 20/37] Bump clap from 4.4.4 to 4.4.5 (#1818) Bumps [clap](https://github.com/clap-rs/clap) from 4.4.4 to 4.4.5. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.4...v4.4.5) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 740b12364b..5fba34d411 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,9 +1208,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.4" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" +checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" dependencies = [ "clap_builder", "clap_derive", @@ -1218,9 +1218,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.4" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" +checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" dependencies = [ "anstream", "anstyle", From bed3851497e5c3476ebf207665e64c0a0fa87e41 Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Tue, 26 Sep 2023 10:41:47 -0400 Subject: [PATCH 21/37] nonzero base size for create_random_transaction --- crates/hotshot/src/demo.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index cec7120acd..ca00c535f3 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -103,10 +103,8 @@ impl TestableState for SDemoState { _rng: &mut dyn rand::RngCore, padding: u64, ) -> ::Transaction { - if padding == 0 { - panic!("Padding should be nonzero for VID computation to work."); - } - VIDTransaction(vec![0; padding as usize]) + const RANDOM_TX_BASE_SIZE: usize = 8; + VIDTransaction(vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]) } } /// Implementation of [`NodeType`] for [`VDemoNode`] From fdf4c13d964ab63d004b83fd5a46f58a91693ab3 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Tue, 26 Sep 2023 10:53:57 -0400 Subject: [PATCH 22/37] Don't use libp2p cache by default (#1820) * don't use cache by default * clarifying comment --- crates/hotshot/src/traits/networking/libp2p_network.rs | 4 ---- crates/libp2p-networking/src/network/node/config.rs | 5 ++--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/hotshot/src/traits/networking/libp2p_network.rs b/crates/hotshot/src/traits/networking/libp2p_network.rs index ebb68e7d01..52ed2b73bc 100644 --- a/crates/hotshot/src/traits/networking/libp2p_network.rs +++ b/crates/hotshot/src/traits/networking/libp2p_network.rs @@ -198,8 +198,6 @@ where // setting to sane defaults .ttl(None) .republication_interval(None) - // this removes the cache for tests - .dht_cache_location(None) .build() .unwrap() } else { @@ -220,8 +218,6 @@ where // setting to sane defaults .ttl(None) .republication_interval(None) - // this removes the cache for tests - .dht_cache_location(None) .build() .unwrap() }; diff --git a/crates/libp2p-networking/src/network/node/config.rs b/crates/libp2p-networking/src/network/node/config.rs index 82897c0de5..d97097e8e1 100644 --- a/crates/libp2p-networking/src/network/node/config.rs +++ b/crates/libp2p-networking/src/network/node/config.rs @@ -24,9 +24,8 @@ pub struct NetworkNodeConfig { #[builder(setter(into, strip_option), default = "DEFAULT_REPLICATION_FACTOR")] pub replication_factor: Option, - /// location of the dht cache - /// default is "dht.cache" in the current directory - #[builder(default = "Some(\"dht.cache\".to_string())")] + /// location of the dht cache, default is None + #[builder(default = "None")] pub dht_cache_location: Option, #[builder(default)] From 8539bb2f842299b566c6a3bec52e8f6601bed135 Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Tue, 26 Sep 2023 11:27:49 -0400 Subject: [PATCH 23/37] fix build break after merge main --- crates/task-impls/src/transactions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index e419115d90..4b0b46cfcf 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -307,7 +307,7 @@ where TYPES, Message, Certificate = DACertificate, - Commitment = TYPES::BlockType, + Commitment = Commitment, >, { #[instrument(skip_all, fields(id = self.id, view = *self.cur_view), name = "Transaction Handling Task", level = "error")] From 219a4e943ec68b06a195f567b7d2c2c52d2029c1 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Tue, 26 Sep 2023 11:55:31 -0400 Subject: [PATCH 24/37] Prune libp2p config file (#1819) * prune libp2p config file * fmt --- .../default-libp2p-run-config.toml | 7 +--- crates/orchestrator/src/config.rs | 35 +++++++++++-------- crates/orchestrator/src/lib.rs | 8 ++--- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/crates/orchestrator/default-libp2p-run-config.toml b/crates/orchestrator/default-libp2p-run-config.toml index 5757f4d9f9..a865225c8f 100644 --- a/crates/orchestrator/default-libp2p-run-config.toml +++ b/crates/orchestrator/default-libp2p-run-config.toml @@ -39,7 +39,6 @@ padding = 10 start_delay_seconds = 60 [libp2p_config] -num_bootstrap_nodes = 5 index_ports = true bootstrap_mesh_n_high = 4 bootstrap_mesh_n_low = 4 @@ -49,11 +48,7 @@ mesh_n_high = 4 mesh_n_low = 4 mesh_outbound_min = 2 mesh_n = 4 -next_view_timeout = 10 -propose_min_round_time = 0 -propose_max_round_time = 10 online_time = 10 -num_txn_per_round = 10 base_port = 9000 [config] @@ -68,7 +63,7 @@ timeout_ratio = [ ] round_start_delay = 1 start_delay = 1 -num_bootstrap = 4 +num_bootstrap = 5 [config.propose_min_round_time] secs = 0 diff --git a/crates/orchestrator/src/config.rs b/crates/orchestrator/src/config.rs index 05a38b615c..86dc6c5ae2 100644 --- a/crates/orchestrator/src/config.rs +++ b/crates/orchestrator/src/config.rs @@ -8,7 +8,7 @@ use std::{ #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] pub struct Libp2pConfig { pub bootstrap_nodes: Vec<(SocketAddr, Vec)>, - pub num_bootstrap_nodes: u64, + pub num_bootstrap_nodes: usize, pub public_ip: IpAddr, pub base_port: u16, pub node_index: u64, @@ -22,15 +22,14 @@ pub struct Libp2pConfig { pub mesh_outbound_min: usize, pub mesh_n: usize, pub next_view_timeout: u64, - pub propose_min_round_time: u64, - pub propose_max_round_time: u64, + pub propose_min_round_time: Duration, + pub propose_max_round_time: Duration, pub online_time: u64, - pub num_txn_per_round: u64, + pub num_txn_per_round: usize, } #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] pub struct Libp2pConfigFile { - pub num_bootstrap_nodes: u64, pub index_ports: bool, pub bootstrap_mesh_n_high: usize, pub bootstrap_mesh_n_low: usize, @@ -40,11 +39,7 @@ pub struct Libp2pConfigFile { pub mesh_n_low: usize, pub mesh_outbound_min: usize, pub mesh_n: usize, - pub next_view_timeout: u64, - pub propose_min_round_time: u64, - pub propose_max_round_time: u64, pub online_time: u64, - pub num_txn_per_round: u64, pub base_port: u16, } @@ -59,6 +54,10 @@ pub struct WebServerConfig { pub struct NetworkConfig { pub rounds: usize, pub transactions_per_round: usize, + pub num_bootrap: usize, + pub next_view_timeout: u64, + pub propose_min_round_time: Duration, + pub propose_max_round_time: Duration, pub node_index: u64, pub seed: [u8; 32], pub padding: usize, @@ -88,6 +87,10 @@ impl Default for NetworkConfig { web_server_config: None, da_web_server_config: None, _key_type_phantom: PhantomData, + next_view_timeout: 10, + num_bootrap: 5, + propose_min_round_time: Duration::from_secs(0), + propose_max_round_time: Duration::from_secs(10), } } } @@ -126,10 +129,14 @@ impl From for NetworkConfig { rounds: val.rounds, transactions_per_round: val.transactions_per_round, node_index: 0, + num_bootrap: val.config.num_bootstrap, + next_view_timeout: val.config.next_view_timeout, + propose_max_round_time: val.config.propose_max_round_time, + propose_min_round_time: val.config.propose_min_round_time, seed: val.seed, padding: val.padding, libp2p_config: val.libp2p_config.map(|libp2p_config| Libp2pConfig { - num_bootstrap_nodes: libp2p_config.num_bootstrap_nodes, + num_bootstrap_nodes: val.config.num_bootstrap, index_ports: libp2p_config.index_ports, bootstrap_nodes: Vec::new(), public_ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), @@ -143,11 +150,11 @@ impl From for NetworkConfig { mesh_n_low: libp2p_config.mesh_n_low, mesh_outbound_min: libp2p_config.mesh_outbound_min, mesh_n: libp2p_config.mesh_n, - next_view_timeout: libp2p_config.next_view_timeout, - propose_min_round_time: libp2p_config.propose_min_round_time, - propose_max_round_time: libp2p_config.propose_max_round_time, + next_view_timeout: val.config.next_view_timeout, + propose_min_round_time: val.config.propose_min_round_time, + propose_max_round_time: val.config.propose_max_round_time, online_time: libp2p_config.online_time, - num_txn_per_round: libp2p_config.num_txn_per_round, + num_txn_per_round: val.transactions_per_round, }), config: val.config.into(), key_type_name: std::any::type_name::().to_string(), diff --git a/crates/orchestrator/src/lib.rs b/crates/orchestrator/src/lib.rs index 93efa501e7..d3faa7d410 100644 --- a/crates/orchestrator/src/lib.rs +++ b/crates/orchestrator/src/lib.rs @@ -116,9 +116,7 @@ where if self.config.libp2p_config.clone().is_some() { let libp2p_config_clone = self.config.libp2p_config.clone().unwrap(); // Designate node as bootstrap node and store its identity information - if libp2p_config_clone.bootstrap_nodes.len() - < libp2p_config_clone.num_bootstrap_nodes.try_into().unwrap() - { + if libp2p_config_clone.bootstrap_nodes.len() < libp2p_config_clone.num_bootstrap_nodes { let port_index = match libp2p_config_clone.index_ports { true => node_index, false => 0, @@ -145,9 +143,7 @@ where ) -> Result, ServerError> { if self.config.libp2p_config.is_some() { let libp2p_config = self.config.clone().libp2p_config.unwrap(); - if libp2p_config.bootstrap_nodes.len() - < libp2p_config.num_bootstrap_nodes.try_into().unwrap() - { + if libp2p_config.bootstrap_nodes.len() < libp2p_config.num_bootstrap_nodes { return Err(ServerError { status: tide_disco::StatusCode::BadRequest, message: "Not enough bootstrap nodes have registered".to_string(), From 913f5aae22d2d50f54455228b7841aee7b3cca66 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Tue, 26 Sep 2023 16:28:34 -0700 Subject: [PATCH 25/37] Integrate with jellyfish update, update parameters and add issues --- Cargo.lock | 6 +- Cargo.toml | 6 +- .../default-libp2p-run-config.toml | 4 +- crates/orchestrator/default-run-config.toml | 2 + .../default-web-server-run-config.toml | 2 + crates/orchestrator/src/config.rs | 2 +- crates/task-impls/src/transactions.rs | 76 +++++++++---------- 7 files changed, 50 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a747048d8..1ba4c92226 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3270,7 +3270,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jf-primitives" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#f6866c5395405f807e62516b5d56d9dc390aeb61" +source = "git+https://github.com/EspressoSystems/jellyfish?branch=gg/376#798700771a90c16ee327404dda5bb742d6566d21" dependencies = [ "anyhow", "ark-bls12-377", @@ -3315,7 +3315,7 @@ dependencies = [ [[package]] name = "jf-relation" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#f6866c5395405f807e62516b5d56d9dc390aeb61" +source = "git+https://github.com/EspressoSystems/jellyfish?branch=gg/376#798700771a90c16ee327404dda5bb742d6566d21" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "jf-utils" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#f6866c5395405f807e62516b5d56d9dc390aeb61" +source = "git+https://github.com/EspressoSystems/jellyfish?branch=gg/376#798700771a90c16ee327404dda5bb742d6566d21" dependencies = [ "ark-ec", "ark-ff", diff --git a/Cargo.toml b/Cargo.toml index 10990e7437..ba55fcf028 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,9 +52,9 @@ either = { version = "1.8" } espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", tag = "0.4.1" } ethereum-types = { version = "0.14.1", features = ["impl-serde"] } futures = "0.3.28" -jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish" } -jf-relation = { git = "https://github.com/EspressoSystems/jellyfish" } -jf-utils = { git = "https://github.com/espressosystems/jellyfish" } +jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish", branch = "gg/376" } +jf-relation = { git = "https://github.com/EspressoSystems/jellyfish", branch = "gg/376" } +jf-utils = { git = "https://github.com/espressosystems/jellyfish", branch = "gg/376" } libp2p-identity = "0.2" libp2p-networking = { path = "./crates/libp2p-networking", version = "0.1.0", default-features = false } libp2p-swarm-derive = { version = "=0.33.0" } diff --git a/crates/orchestrator/default-libp2p-run-config.toml b/crates/orchestrator/default-libp2p-run-config.toml index 5892d3d95e..c217d24d1c 100644 --- a/crates/orchestrator/default-libp2p-run-config.toml +++ b/crates/orchestrator/default-libp2p-run-config.toml @@ -69,8 +69,8 @@ num_bootstrap = 5 secs = 0 nanos = 0 +# TODO (Keyao) Clean up configuration parameters. +# [config.propose_max_round_time] -# TODO Update libp2p config to use consistent propose_max_round_time. -# secs = 2 nanos = 0 diff --git a/crates/orchestrator/default-run-config.toml b/crates/orchestrator/default-run-config.toml index b8a4b19478..ee8333f80a 100644 --- a/crates/orchestrator/default-run-config.toml +++ b/crates/orchestrator/default-run-config.toml @@ -55,6 +55,8 @@ num_bootstrap = 4 secs = 0 nanos = 0 +# TODO (Keyao) Clean up configuration parameters. +# [config.propose_max_round_time] secs = 2 nanos = 0 diff --git a/crates/orchestrator/default-web-server-run-config.toml b/crates/orchestrator/default-web-server-run-config.toml index 28229f4d76..c5d0bd0253 100644 --- a/crates/orchestrator/default-web-server-run-config.toml +++ b/crates/orchestrator/default-web-server-run-config.toml @@ -56,6 +56,8 @@ num_bootstrap = 4 secs = 0 nanos = 0 +# TODO (Keyao) Clean up configuration parameters. +# [config.propose_max_round_time] secs = 2 nanos = 0 diff --git a/crates/orchestrator/src/config.rs b/crates/orchestrator/src/config.rs index 86dc6c5ae2..f61911d944 100644 --- a/crates/orchestrator/src/config.rs +++ b/crates/orchestrator/src/config.rs @@ -230,7 +230,7 @@ fn default_config() -> HotShotConfigFile { total_nodes: NonZeroUsize::new(10).unwrap(), committee_nodes: 5, max_transactions: NonZeroUsize::new(100).unwrap(), - min_transactions: 0, + min_transactions: 1, next_view_timeout: 10000, timeout_ratio: (11, 10), round_start_delay: 1, diff --git a/crates/task-impls/src/transactions.rs b/crates/task-impls/src/transactions.rs index 4b0b46cfcf..c682f5f38d 100644 --- a/crates/task-impls/src/transactions.rs +++ b/crates/task-impls/src/transactions.rs @@ -237,48 +237,46 @@ where drop(consensus); let txns = self.wait_for_transactions(parent_leaf).await?; + // TODO (Keyao) Determine whether to allow empty transaction when proposing a block. + // debug!("Prepare VID shares"); - if !txns.is_empty() { - // TODO https://github.com/EspressoSystems/HotShot/issues/1686 - let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); - let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); - // TODO https://github.com/EspressoSystems/jellyfish/issues/375 - let mut txns_flatten = Vec::new(); - for txn in &txns { - txns_flatten.extend(txn.0.clone()); - } - let vid_disperse = vid.disperse(&txns_flatten).unwrap(); - let block = VIDBlockPayload { - transactions: txns, - commitment: vid_disperse.commit, - }; - - self.event_stream - .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) - .await; - - // TODO (Keyao) Determine and update where to publish VidDisperseSend. - // - self.event_stream - .publish(SequencingHotShotEvent::VidDisperseSend( - Proposal { - data: VidDisperse { - view_number: view + 1, - commitment: block.commit(), - shares: vid_disperse.shares, - common: vid_disperse.common, - }, - // TODO (Keyao) This is also signed in DA task. - signature: self - .committee_exchange - .sign_da_proposal(&block.commit()), - }, - // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 - self.committee_exchange.public_key().clone(), - )) - .await; + // TODO https://github.com/EspressoSystems/HotShot/issues/1686 + let srs = hotshot_types::data::test_srs(NUM_STORAGE_NODES); + let vid = VidScheme::new(NUM_CHUNKS, NUM_STORAGE_NODES, &srs).unwrap(); + // TODO https://github.com/EspressoSystems/jellyfish/issues/375 + let mut txns_flatten = Vec::new(); + for txn in &txns { + txns_flatten.extend(txn.0.clone()); } + let vid_disperse = vid.disperse(&txns_flatten).unwrap(); + let block = VIDBlockPayload { + transactions: txns, + commitment: vid_disperse.commit, + }; + + self.event_stream + .publish(SequencingHotShotEvent::BlockReady(block.clone(), view + 1)) + .await; + + // TODO (Keyao) Determine and update where to publish VidDisperseSend. + // + self.event_stream + .publish(SequencingHotShotEvent::VidDisperseSend( + Proposal { + data: VidDisperse { + view_number: view + 1, + commitment: block.commit(), + shares: vid_disperse.shares, + common: vid_disperse.common, + }, + // TODO (Keyao) This is also signed in DA task. + signature: self.committee_exchange.sign_da_proposal(&block.commit()), + }, + // TODO don't send to committee, send to quorum (consensus.rs) https://github.com/EspressoSystems/HotShot/issues/1696 + self.committee_exchange.public_key().clone(), + )) + .await; return None; } SequencingHotShotEvent::Shutdown => { From dfca82ef5ff353247a06fa01448954cfa0924651 Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Wed, 27 Sep 2023 10:10:47 -0400 Subject: [PATCH 26/37] clippy appeasement --- crates/hotshot/src/demo.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index cac2dcfc75..81cac76f4b 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -103,6 +103,7 @@ impl TestableState for SDemoState { _rng: &mut dyn rand::RngCore, padding: u64, ) -> ::Transaction { + /// clippy appeasement for `RANDOM_TX_BASE_SIZE` const RANDOM_TX_BASE_SIZE: usize = 8; VIDTransaction(vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]) } From 0bb432e82404c6bcc8c105ce3bf57c6ba96a7238 Mon Sep 17 00:00:00 2001 From: Gus Gutoski Date: Wed, 27 Sep 2023 10:20:22 -0400 Subject: [PATCH 27/37] jellyfish dep use main branch --- Cargo.lock | 6 +++--- Cargo.toml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ba4c92226..23c5d0ff25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3270,7 +3270,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jf-primitives" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish?branch=gg/376#798700771a90c16ee327404dda5bb742d6566d21" +source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" dependencies = [ "anyhow", "ark-bls12-377", @@ -3315,7 +3315,7 @@ dependencies = [ [[package]] name = "jf-relation" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish?branch=gg/376#798700771a90c16ee327404dda5bb742d6566d21" +source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "jf-utils" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish?branch=gg/376#798700771a90c16ee327404dda5bb742d6566d21" +source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" dependencies = [ "ark-ec", "ark-ff", diff --git a/Cargo.toml b/Cargo.toml index ba55fcf028..10990e7437 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,9 +52,9 @@ either = { version = "1.8" } espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", tag = "0.4.1" } ethereum-types = { version = "0.14.1", features = ["impl-serde"] } futures = "0.3.28" -jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish", branch = "gg/376" } -jf-relation = { git = "https://github.com/EspressoSystems/jellyfish", branch = "gg/376" } -jf-utils = { git = "https://github.com/espressosystems/jellyfish", branch = "gg/376" } +jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish" } +jf-relation = { git = "https://github.com/EspressoSystems/jellyfish" } +jf-utils = { git = "https://github.com/espressosystems/jellyfish" } libp2p-identity = "0.2" libp2p-networking = { path = "./crates/libp2p-networking", version = "0.1.0", default-features = false } libp2p-swarm-derive = { version = "=0.33.0" } From bb2008a5b2127200aebc51d0a9a2073660614a24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:24:46 -0400 Subject: [PATCH 28/37] Bump sha2 from 0.10.7 to 0.10.8 (#1824) Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.10.7 to 0.10.8. - [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.7...sha2-v0.10.8) --- updated-dependencies: - dependency-name: sha2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5fba34d411..b8989d5610 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,7 +286,7 @@ dependencies = [ "blake2", "derivative", "digest 0.10.7", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -2006,7 +2006,7 @@ dependencies = [ "ed25519", "rand_core 0.6.4", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "zeroize", ] @@ -2832,7 +2832,7 @@ dependencies = [ "rand_chacha 0.3.1", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "snafu", "tagged-base64 0.2.4", "time 0.3.29", @@ -3305,7 +3305,7 @@ dependencies = [ "rand_chacha 0.3.1", "rayon", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "sha3", "tagged-base64 0.3.3", "typenum", @@ -3350,7 +3350,7 @@ dependencies = [ "digest 0.10.7", "rayon", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "tagged-base64 0.3.3", ] @@ -3603,7 +3603,7 @@ dependencies = [ "rand 0.8.5", "regex", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "unsigned-varint", "void", @@ -3647,7 +3647,7 @@ dependencies = [ "rand 0.8.5", "ring", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "thiserror", "zeroize", ] @@ -3673,7 +3673,7 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "serde", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "thiserror", "uint", @@ -3781,7 +3781,7 @@ dependencies = [ "once_cell", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.8", "snow", "static_assertions", "thiserror", @@ -4836,7 +4836,7 @@ checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -5835,9 +5835,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -6026,7 +6026,7 @@ dependencies = [ "rand_core 0.6.4", "ring", "rustc_version 0.4.0", - "sha2 0.10.7", + "sha2 0.10.8", "subtle", ] From 996400ef9ef1e3c93cced32da60e303164d588a4 Mon Sep 17 00:00:00 2001 From: Keyao Shen Date: Wed, 27 Sep 2023 10:21:44 -0700 Subject: [PATCH 29/37] Revert cargo.lock change --- Cargo.lock | 464 +++++++++++++++++++++++------------------------------ 1 file changed, 205 insertions(+), 259 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0dd26a59ba..3c1554b852 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" dependencies = [ "memchr", ] @@ -178,9 +178,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" [[package]] name = "anstyle-parse" @@ -575,7 +575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener 2.5.3", + "event-listener", "futures-core", ] @@ -601,23 +601,24 @@ dependencies = [ [[package]] name = "async-dup" -version = "1.2.3" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865d94538a2d4f7197f9e08daf94203c06be78fe87a9d293ba4dd718028c5783" +checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" dependencies = [ "futures-io", + "simple-mutex", ] [[package]] name = "async-executor" -version = "1.5.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f2db9467baa66a700abce2a18c5ad793f6f83310aca1284796fc3921d113fd" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand 2.0.1", + "fastrand", "futures-lite", "slab", ] @@ -679,7 +680,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.23", + "rustix", "slab", "socket2 0.4.9", "waker-fn", @@ -691,53 +692,36 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener 2.5.3", + "event-listener", ] [[package]] name = "async-net" -version = "1.8.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" +checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" dependencies = [ "async-io", + "autocfg", "blocking", "futures-lite", ] [[package]] name = "async-process" -version = "1.8.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf012553ce51eb7aa6dc2143804cc8252bd1cb681a1c5cb7fa94ca88682dee1d" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" dependencies = [ "async-io", "async-lock", - "async-signal", + "autocfg", "blocking", "cfg-if", - "event-listener 3.0.0", + "event-listener", "futures-lite", - "rustix 0.38.14", - "windows-sys", -] - -[[package]] -name = "async-signal" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4af361a844928cb7d36590d406709473a1b574f443094422ef166daa3b493208" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "concurrent-queue", - "futures-core", - "futures-io", - "libc", - "signal-hook-registry", - "slab", + "rustix", + "signal-hook", "windows-sys", ] @@ -800,9 +784,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.4.1" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "async-trait" @@ -812,7 +796,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -848,7 +832,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures-sink", "futures-util", "memchr", @@ -857,9 +841,9 @@ dependencies = [ [[package]] name = "atomic-waker" -version = "1.1.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" [[package]] name = "atomic_enum" @@ -887,7 +871,7 @@ dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", - "bytes 1.5.0", + "bytes 1.4.0", "futures-util", "http", "http-body", @@ -913,7 +897,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", - "bytes 1.5.0", + "bytes 1.4.0", "futures-util", "http", "http-body", @@ -958,9 +942,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" [[package]] name = "base64ct" @@ -1051,18 +1035,17 @@ dependencies = [ [[package]] name = "blocking" -version = "1.4.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94c4ef1f913d78636d78d538eec1f18de81e481f44b1be0a81060090530846e1" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" dependencies = [ "async-channel", "async-lock", "async-task", - "fastrand 2.0.1", - "futures-io", + "atomic-waker", + "fastrand", "futures-lite", - "piper", - "tracing", + "log", ] [[package]] @@ -1086,9 +1069,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byte-slice-cast" @@ -1110,9 +1093,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" dependencies = [ "serde", ] @@ -1183,9 +1166,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1254,7 +1237,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -1316,9 +1299,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" dependencies = [ "crossbeam-utils", ] @@ -1561,7 +1544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "704722d1d929489c8528bb1882805700f1ba20f54325704973e786352320b1ed" dependencies = [ "blake2", - "curve25519-dalek 4.1.1", + "curve25519-dalek 4.0.0", "rand_core 0.6.4", "serdect", ] @@ -1612,9 +1595,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.66+curl-8.3.0" +version = "0.4.65+curl-8.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70c44a72e830f0e40ad90dda8a6ab6ed6314d39776599a58a2e5e37fbc6db5b9" +checksum = "961ba061c9ef2fe34bbd12b807152d96f0badd2bebe7b90ce6c8c8b7572a0986" dependencies = [ "cc", "libc", @@ -1623,7 +1606,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys", + "winapi", ] [[package]] @@ -1641,9 +1624,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2" dependencies = [ "cfg-if", "cpufeatures", @@ -1664,7 +1647,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -1732,7 +1715,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -1754,7 +1737,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -1848,7 +1831,7 @@ checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -1970,7 +1953,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -1999,9 +1982,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" [[package]] name = "ed25519" @@ -2019,7 +2002,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" dependencies = [ - "curve25519-dalek 4.1.1", + "curve25519-dalek 4.0.0", "ed25519", "rand_core 0.6.4", "serde", @@ -2154,17 +2137,6 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" -[[package]] -name = "event-listener" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite 0.2.13", -] - [[package]] name = "eyre" version = "0.6.8" @@ -2184,17 +2156,11 @@ dependencies = [ "instant", ] -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - [[package]] name = "fiat-crypto" -version = "0.2.1" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" [[package]] name = "fixed-hash" @@ -2317,7 +2283,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand 1.9.0", + "fastrand", "futures-core", "futures-io", "memchr", @@ -2334,7 +2300,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -2479,7 +2445,7 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "fnv", "futures-core", "futures-sink", @@ -2537,9 +2503,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -2915,7 +2881,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "fnv", "itoa 1.0.9", ] @@ -2926,7 +2892,7 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "http", "pin-project-lite 0.2.13", ] @@ -2991,7 +2957,7 @@ version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures-channel", "futures-core", "futures-util", @@ -3207,7 +3173,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", ] [[package]] @@ -3236,7 +3202,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.4", + "socket2 0.5.3", "widestring", "windows-sys", "winreg", @@ -3434,9 +3400,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libnghttp2-sys" @@ -3454,7 +3420,7 @@ version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32d07d1502a027366d55afe187621c2d7895dc111a3df13b35fed698049681d7" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures", "futures-timer", "getrandom 0.2.10", @@ -3535,9 +3501,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.40.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" +checksum = "ef7dd7b09e71aac9271c60031d0e558966cdb3253ba0308ab369bb2de80630d0" dependencies = [ "either", "fnv", @@ -3617,9 +3583,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d157562dba6017193e5285acf6b1054759e83540bfd79f75b69d6ce774c88da" dependencies = [ "asynchronous-codec", - "base64 0.21.4", + "base64 0.21.3", "byteorder", - "bytes 1.5.0", + "bytes 1.4.0", "either", "fnv", "futures", @@ -3688,13 +3654,13 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.44.5" +version = "0.44.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c5c483b1e90e79409711f515c5bea5de9c4d772a245b1ac01a2233fbcb67fe" +checksum = "fc125f83d8f75322c79e4ade74677d299b34aa5c9d9b5251c03ec28c683cb765" dependencies = [ "arrayvec", "asynchronous-codec", - "bytes 1.5.0", + "bytes 1.4.0", "either", "fnv", "futures", @@ -3705,7 +3671,6 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", - "quick-protobuf-codec", "rand 0.8.5", "serde", "sha2 0.10.8", @@ -3732,7 +3697,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2 0.5.4", + "socket2 0.5.3", "tokio", "trust-dns-proto", "void", @@ -3805,8 +3770,8 @@ version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71ce70757f2c0d82e9a3ef738fb10ea0723d16cec37f078f719e2c247704c1bb" dependencies = [ - "bytes 1.5.0", - "curve25519-dalek 4.1.1", + "bytes 1.4.0", + "curve25519-dalek 4.0.0", "futures", "libp2p-core", "libp2p-identity", @@ -3826,9 +3791,9 @@ dependencies = [ [[package]] name = "libp2p-ping" -version = "0.43.1" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e702d75cd0827dfa15f8fd92d15b9932abe38d10d21f47c50438c71dd1b5dae3" +checksum = "3cd5ee3270229443a2b34b27ed0cb7470ef6b4a6e45e54e89a8771fa683bab48" dependencies = [ "either", "futures", @@ -3849,7 +3814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37266c683a757df713f7dcda0cdcb5ad4681355ffa1b37b77c113c176a531195" dependencies = [ "asynchronous-codec", - "bytes 1.5.0", + "bytes 1.4.0", "futures", "libp2p-core", "libp2p-identity", @@ -3879,7 +3844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cb763e88f9a043546bfebd3575f340e7dd3d6c1b2cf2629600ec8965360c63a" dependencies = [ "async-std", - "bytes 1.5.0", + "bytes 1.4.0", "futures", "futures-timer", "if-watch", @@ -3891,7 +3856,7 @@ dependencies = [ "quinn", "rand 0.8.5", "rustls", - "socket2 0.5.4", + "socket2 0.5.3", "thiserror", "tokio", ] @@ -3903,7 +3868,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb07202cdf103486709fda5d9d10a0297a8ba01c212b1e19b7943c45c1bd7d6" dependencies = [ "asynchronous-codec", - "bytes 1.5.0", + "bytes 1.4.0", "either", "futures", "futures-timer", @@ -3964,9 +3929,9 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.43.5" +version = "0.43.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab94183f8fc2325817835b57946deb44340c99362cd4606c0a5717299b2ba369" +checksum = "28016944851bd73526d3c146aabf0fa9bbe27c558f080f9e5447da3a1772c01a" dependencies = [ "async-std", "either", @@ -3996,7 +3961,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -4013,7 +3978,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "socket2 0.5.4", + "socket2 0.5.3", "tokio", ] @@ -4166,12 +4131,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" -[[package]] -name = "linux-raw-sys" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" - [[package]] name = "lock_api" version = "0.4.10" @@ -4243,9 +4202,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" -version = "0.7.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" [[package]] name = "maud" @@ -4403,9 +4362,9 @@ dependencies = [ [[package]] name = "multihash" -version = "0.19.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" +checksum = "2fd59dcc2bbe70baabeac52cd22ae52c55eefe6c38ff11a9439f16a350a939f2" dependencies = [ "core2", "serde", @@ -4418,7 +4377,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures", "log", "pin-project", @@ -4527,7 +4486,7 @@ name = "netlink-proto" version = "0.9.2" source = "git+https://github.com/espressosystems/netlink.git#1347bed011eeae7ece9851773906c4a3c80a5d77" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures", "log", "netlink-packet-core 0.4.2 (git+https://github.com/espressosystems/netlink.git)", @@ -4541,7 +4500,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures", "log", "netlink-packet-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4556,7 +4515,7 @@ version = "0.8.2" source = "git+https://github.com/espressosystems/netlink.git#1347bed011eeae7ece9851773906c4a3c80a5d77" dependencies = [ "async-io", - "bytes 1.5.0", + "bytes 1.4.0", "futures", "libc", "log", @@ -4569,7 +4528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" dependencies = [ "async-io", - "bytes 1.5.0", + "bytes 1.4.0", "futures", "libc", "log", @@ -4715,9 +4674,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" dependencies = [ "cc", "libc", @@ -4781,9 +4740,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" [[package]] name = "parking_lot" @@ -4837,9 +4796,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" dependencies = [ "memchr", "thiserror", @@ -4848,9 +4807,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a" dependencies = [ "pest", "pest_generator", @@ -4858,22 +4817,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" dependencies = [ "once_cell", "pest", @@ -4897,7 +4856,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -4924,17 +4883,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0" -[[package]] -name = "piper" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" -dependencies = [ - "atomic-waker", - "fastrand 2.0.1", - "futures-io", -] - [[package]] name = "pkcs8" version = "0.10.2" @@ -5085,14 +5033,14 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -5117,7 +5065,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -5126,7 +5074,7 @@ version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "prost-derive", ] @@ -5174,7 +5122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" dependencies = [ "asynchronous-codec", - "bytes 1.5.0", + "bytes 1.4.0", "quick-protobuf", "thiserror", "unsigned-varint", @@ -5199,7 +5147,7 @@ checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" dependencies = [ "async-io", "async-std", - "bytes 1.5.0", + "bytes 1.4.0", "futures-io", "pin-project-lite 0.2.13", "quinn-proto", @@ -5217,7 +5165,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c78e758510582acc40acb90458401172d41f1016f8c9dde89e49677afb7eec1" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "rand 0.8.5", "ring", "rustc-hash", @@ -5234,9 +5182,9 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "libc", - "socket2 0.5.4", + "socket2 0.5.3", "tracing", "windows-sys", ] @@ -5329,9 +5277,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -5339,12 +5287,14 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ + "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", + "num_cpus", ] [[package]] @@ -5463,7 +5413,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "rustc-hex", ] @@ -5571,7 +5521,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.19", + "semver 1.0.18", ] [[package]] @@ -5593,20 +5543,7 @@ dependencies = [ "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] - -[[package]] -name = "rustix" -version = "0.38.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys 0.4.7", + "linux-raw-sys", "windows-sys", ] @@ -5624,9 +5561,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring", "untrusted", @@ -5700,9 +5637,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "semver-parser" @@ -5733,7 +5670,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -5810,7 +5747,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" dependencies = [ - "base64 0.21.4", + "base64 0.21.3", "chrono", "hex", "indexmap 1.9.3", @@ -5830,7 +5767,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -5842,7 +5779,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -5981,6 +5918,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +[[package]] +name = "simple-mutex" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" +dependencies = [ + "event-listener", +] + [[package]] name = "slab" version = "0.4.9" @@ -6003,9 +5949,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "smartcow" @@ -6076,7 +6022,7 @@ dependencies = [ "aes-gcm 0.9.2", "blake2", "chacha20poly1305 0.9.1", - "curve25519-dalek 4.1.1", + "curve25519-dalek 4.0.0", "rand_core 0.6.4", "ring", "rustc_version 0.4.0", @@ -6096,9 +6042,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", "windows-sys", @@ -6111,7 +6057,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", - "bytes 1.5.0", + "bytes 1.4.0", "futures", "httparse", "log", @@ -6258,7 +6204,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -6309,15 +6255,15 @@ dependencies = [ [[package]] name = "sval" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d11eec9fbe2bc8bc71e7349f0e7534db9a96d961fb9f302574275b7880ad06" +checksum = "8b031320a434d3e9477ccf9b5756d57d4272937b8d22cb88af80b7633a1b78b1" [[package]] name = "sval_buffer" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7451f69a93c5baf2653d5aa8bb4178934337f16c22830a50b06b386f72d761" +checksum = "6bf7e9412af26b342f3f2cc5cc4122b0105e9d16eb76046cd14ed10106cf6028" dependencies = [ "sval", "sval_ref", @@ -6325,18 +6271,18 @@ dependencies = [ [[package]] name = "sval_dynamic" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f5a2cc12b4da2adfb59d5eedfd9b174a23cc3fae84cec71dcbcd9302068f5" +checksum = "a0ef628e8a77a46ed3338db8d1b08af77495123cc229453084e47cd716d403cf" dependencies = [ "sval", ] [[package]] name = "sval_fmt" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f578b2301341e246d00b35957f2952c4ec554ad9c7cfaee10bc86bc92896578" +checksum = "7dc09e9364c2045ab5fa38f7b04d077b3359d30c4c2b3ec4bae67a358bd64326" dependencies = [ "itoa 1.0.9", "ryu", @@ -6345,9 +6291,9 @@ dependencies = [ [[package]] name = "sval_json" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8346c00f5dc6efe18bea8d13c1f7ca4f112b20803434bf3657ac17c0f74cbc4b" +checksum = "ada6f627e38cbb8860283649509d87bc4a5771141daa41c78fd31f2b9485888d" dependencies = [ "itoa 1.0.9", "ryu", @@ -6356,18 +6302,18 @@ dependencies = [ [[package]] name = "sval_ref" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6617cc89952f792aebc0f4a1a76bc51e80c70b18c491bd52215c7989c4c3dd06" +checksum = "703ca1942a984bd0d9b5a4c0a65ab8b4b794038d080af4eb303c71bc6bf22d7c" dependencies = [ "sval", ] [[package]] name = "sval_serde" -version = "2.8.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3d1e59f023341d9af75d86f3bc148a6704f3f831eef0dd90bbe9cb445fa024" +checksum = "830926cd0581f7c3e5d51efae4d35c6b6fc4db583842652891ba2f1bed8db046" dependencies = [ "serde", "sval", @@ -6388,9 +6334,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -6540,22 +6486,22 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -6612,7 +6558,7 @@ dependencies = [ "maud 0.24.0", "parking_lot", "routefinder", - "semver 1.0.19", + "semver 1.0.18", "serde", "serde_json", "serde_with 2.3.3", @@ -6658,7 +6604,7 @@ dependencies = [ "maud 0.25.0", "parking_lot", "routefinder", - "semver 1.0.19", + "semver 1.0.18", "serde", "serde_json", "serde_with 3.3.0", @@ -6796,14 +6742,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ "backtrace", - "bytes 1.5.0", + "bytes 1.4.0", "libc", "mio", "num_cpus", "parking_lot", "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2 0.5.4", + "socket2 0.5.3", "tokio-macros", "tracing", "windows-sys", @@ -6827,7 +6773,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -6843,11 +6789,11 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ - "bytes 1.5.0", + "bytes 1.4.0", "futures-core", "futures-sink", "pin-project-lite 0.2.13", @@ -6906,8 +6852,8 @@ checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ "async-trait", "axum", - "base64 0.21.4", - "bytes 1.5.0", + "base64 0.21.3", + "bytes 1.4.0", "futures-core", "futures-util", "h2", @@ -6979,7 +6925,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] [[package]] @@ -7126,7 +7072,7 @@ checksum = "5fe8dada8c1a3aeca77d6b51a4f1314e0f4b8e438b7b1b71e3ddaca8080e4093" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.5.0", + "bytes 1.4.0", "http", "httparse", "input_buffer", @@ -7146,7 +7092,7 @@ checksum = "983d40747bce878d2fb67d910dcb8bd3eca2b2358540c3cc1b98c027407a3ae3" dependencies = [ "base64 0.13.1", "byteorder", - "bytes 1.5.0", + "bytes 1.4.0", "http", "httparse", "log", @@ -7198,9 +7144,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -7239,12 +7185,12 @@ dependencies = [ [[package]] name = "unsigned-varint" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" +checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" dependencies = [ "asynchronous-codec", - "bytes 1.5.0", + "bytes 1.4.0", ] [[package]] @@ -7339,9 +7285,9 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "want" @@ -7387,7 +7333,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", "wasm-bindgen-shared", ] @@ -7421,7 +7367,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7700,5 +7646,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.31", ] From d1e10d522833655ec54f6f4b619f47409f6bc8ee Mon Sep 17 00:00:00 2001 From: Philippe Camacho Date: Wed, 27 Sep 2023 18:16:10 -0300 Subject: [PATCH 30/37] HotShot paper update (#1827) --- docs/espresso-sequencer-paper.pdf | Bin 796276 -> 791332 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/espresso-sequencer-paper.pdf b/docs/espresso-sequencer-paper.pdf index 6f0976f7c9e7f1c0f0e64016b1c7e1d79d262f88..a5aeb7eac6c34115bb3cdfb8e40ba83111038d14 100644 GIT binary patch delta 222595 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

d><$oLDJwSR6LSe47{VuntM;Kc9XEKjSQp>I za6WiwM6?+*bZ7`y;`RqHnwc#_y;mXGIcg;>e}g<9r0t2Y4%tu2Hmt-rb2;5`kQPg~ z{&bSyyXhopZKi4Oz@vlQ*pc)d``9P{br#FEwy;{-YF#t8KV$LSUur9az4O~B`6=PC ze&l5Ln5k|-M6uH;REPAKUwpE?{)Rv1{pS~>;&UiZchi9SOD|T&==4seG0THa5cDo{XNRLrE>h>JbS~b;C!0FLS&DpTdr>rt`rRxY-?)d(&@VeTN z5_VbUDR$eR2&l1(Kgz+Hia3E~fA)AFe8Y|A%)r)vP2EuWo%3fXq1elq?cCL&7Kb*q z0Q3}aTK9Yoby0hPRDwGfqa8D2R5=bv^-RJla?4}%25WO&?GY}$of(kcWB_K$s$Kpj z5=Y|zn;<4wl2#7p#MS~&kJl0h?~3e(uWm1hfGGyxhs6W}3Uky6w~f9gf7Bn=?AE&G z9bZFG+KiLY40}Yd8airr!btH+M_nyLa1_WU$#AX0TD!W=1!HK2GBOHik` zT=h=rK-y|P?W|)AbJh$?e`ng#mTNwb)KR8z-8&f~a!|xJf2ahr4|%Hfgvfki=Pt`^#VhSjG3C2u&s(1&1563D7Zf?WZ$O{QpSfb6hFW#^alyUQPOZ0>R=|$LD=L{A8qM<#l+hjfnSDj#nr#A!f06JOU&LUs|B93E zw1|5mWVMEfEx5pbXR_HhN73{WvSR-Zy)cV~Z#rUd(vug`@DLC%1dNwbL}PI8nWtXH zG;-o_Vb>cW8~QQ_5c`19Tdj<@+nR;wPpx`0IVoJ3*~p84Dr&+{)ILK$a$?x7;5y|} zn;bEp=gEZE5JOrde~U8vwA}pk@&e6Ux&=_^v4MaLVa1(R`mNznJ3b;Xt0WkgIHg27 zD~1XF*m2h+W%2-P;|7ehcBw%zPqNl0$@b_v9^Ft+e;PlRfLTHCeGLpaI7>3aa+FP? zJ;~H)6*lG;Qd+DHKXyswPYNJg+`ujOMW64-tS zOkl&V;%^68;0T96jMQLbjg1f9uKxN&!FC5VzTwEG1q@#IRX16V$6kIrC_`^LAdbHn z64`p*WoEG1e|wpkrUyRERZBb?6`8oc#(o^@J+RHGn?^n5j>9o1>$~Re2tD$2!+M0z zX3GMH@#@kRsBcsI_TpgPE!J@XF!n%cJ1eUd0|`y-!9o#|ovcAtLEhz2s zQl1QY7arqNxXJV_m$|nsXT^ zQ^Rk=e+>(U<;(LfP&FdgQ4{W1aicFXG$*xf zt(U9;qL8^(YC@y%C}v{o-s?2Dpi)fN3!f~Fc2lWnq#`A4TS8ncQv1sQwb{x*{e`Ei z*F>LoZ)CT+{?-B3B{@d7Ui`!9R{g4N`Myn{e*hBqe)xG>kySIJe$Lp7WbkM|9Y9Uw z@{V;TdX?pJzI^}rirIz1D!XL|M;H>4ormcfII6&g2pbw(R=bKJ?qUjsjwpg;!y)ij3VM;1DO+-KZ_ zf2xR87QROen-ZfA4tPc#7x$9NmVK&IV|P54JlGetxV<$mVXP?+ z7tiZBntIutvK$_;kCJy^{!#i}s+dc$M7%I_d|N!2P!x9Z;*a=hDCn*{K$a~wG$B-B zKWcPE?OG0#%L7aW?IafPx}=NAUIiK%gPPq4Ak{ZRo-n zU((Up`Wn5Ymcet(B&Ac6M6i}YNId~7Nw<-gHQ}hY#BRbE_8@;$-iQr;`R|{ve@;yZ zMSKBd7ie94+IA@iZL~pl`P;R;mlHNym??jSNwUJ&EA_MBYU0hhq*6i*=F7h>w``#t z_uk3%lc#Vpi!J8MOjP>&&sVIlB`nP8gcT=~L=}t_&o6&m($%`+rb3+QI?4+?2j^c5 zwjFd9Aamd_b>_frH6}6K)jpw~f9#y$xT&7oDW`SH={RiteH{sH$Z4KS!C!RB(Z=~= zu?0sn+LIqr!6J|ug4joA{E2ozRzCQ7>(yI>tL*LAaOm3?o}G?2{Azs|$MMP5b*xBsF zj_$0v0~K79U6?nrH$31=FD*&;#axT*anNKlQ~Nzs0CI69-RShWhwq)Cj8g*&R`?#9 z$V-$H)_CTCWd+*KOL390sZKK6w?LSK{gjzUyc@LmZ9$)0^re6II+dW`Mr>-+6=CI< zldAcjCLaic2-07?V20J1fB5_u_h@8dVyAeJoboAh#oH!jswcG1+tT$VSS~0LltZp% zoD0Nz(IHXKKIb|UN}LmRHWw5_D;8u)G+gU+pA#ZgA>qF$i?9n#$>iY9Idj@BpVPfo zEsr#8bxupTO>p%($w^jr9E`;dSXfe|n!fumCSdNn4{sOad*gTEf0&QE8_jge#}~uE z(h{2$DTmpC^gJI;mx0+-;wodjssr`${-R^t-Q%uL|D6=PJSv>`%H<$9c;jul0Lm9< zLv;C%pML?Hy6xW|GKB#uMkjk-hYT+33Lc0q*CB(~Mp-+{l<%Jf7@*}&E^(kg$s}L>Ti6UdSm9~&SQLyJC0-2tLmR&x^Av+cAEx# zD?cWiB@i;%3I^Rc#Lfnl3ezW^jvJ*%@;ZRHx5@5<^HQI&bC%`UiBE|iBbc{RJvv{d zddzZLy0#Y=3w7SvjQX@=4A|z+e8ng6`6Rxd-~DP&A0wR2y6PLTCXLrzuyaZM|d3^79TEr-Ztx2#U-$t_f3}%Y6PxlsrRA&??LLKMFg3XYW zj$Z8a#_k{Jjfo(;9CqJ@JD)#0rOTibS-Zg24bo}L%d%tQm0wd8=|0r1v6dxqX8E$0Jl%v79B)e1}1a9bLyjD5Jc{}pkVfoavV^L0R)j$2h&;cqd z61BXa)I*q8mw6=(&buJjbeSM+0>bTmbeGPqL@wX4f9O++8s`2K?>6MSYXhUx_*7Va zjKTu(@trMr2L@E~!!(@Ty6|aN3-03*9n*lK%W?PUJ9Kcv;E+ZEfM-i9tOl(=yw>q=-&y2`*mR+b(jg+^EzJL2nq zFLndNe~yp*O&?}tVB1-4$%;?gy@k5Hi&L5Cj*0?G6PZyhh8OM1GrTWl>6YOQ>SP=y zTjao0c{y}IaycwmBmWS?d>__F@hQlCy!!^sM8UPaj9NEbqdEG~aEB=D9#@~7xbeCq44k{U!d1UY6;dk_a;*}HU(ci}1;?sc$@Rx}9p)FiUrQ(4 zY3T&@BNJKW6?lmorB4f2wys5fN0i^FKiECje_HjATfT-J-Opxb@AwMB-mwv)GUJ1yr#__k zjO^97llFIU%#i`IBVEBtz95@7ol3~?Zqfz^9iI{+qBK;dJ>ge_A%|Vewt)VL z9kVYIW1rbEHwSB5=b1N#6LS8}G+=w5(^HMGV~OSCxJ$Wo z;55bc%Gd=u+FC3X_x#$b6K!|iB`$C>QFkb_je&FI%Rg^G=BRwI6A#CoyUk_OQ>Exk z<1yvl`6z!Z^ay$W%nDwZy}8P5e@q!F!#vb%&-J){_qCVG!+UpIOb80{yxM&-nB>I2 z0kapY445VsTs9sY!{p z$g!C})WZ>xuC4WUU*6Hv&b}8unMDMjzEf3t2|^cf1mpP1Z&VKeR4h6tfA=a5m6IKu zX2Na0&4k-s(q#~^7aN>ReSe8Fy`2be<@)JO2JKy-?FYJ)GmCMdA}kvy_UCcok@Uki zcV@@B3TMknL|CTzR~^a(o}l~Xa~Ul7Z&2c?u$ZVq2=lbP#$`blLOQt$vHub?jWNgW zI8M(Lvrnlx_Pq>|7z(`pIdH6FtgOy6F5I>!Q$~8tdBqtQz_H)@-W2C7{XbVmMh8^z z;RAw7x(80j?L2Emhi~71`hOdo#?P0r^a2x?vYP@a1UWM`G?(%80v3N+k0!Tq@A?(< zI16FhybpVJ1I^A(0wV|zWZz^x1eOyUu^{Jw@|NG8DzeFD@$OmsL7M%#yLc3fb+gDG z{{4YH{QWm<@b~%4H@|vS;=v!@2%{dp{M$DiUa$xL;M}2veXv#?)|rPdKRtZ^#F&;J zrGUTu6Jv(Ozv`JWDd2y%KmWpW1AoP*k3W3*Ep)(juLG{tA-Sr1P&T!8LMz#Yw&Jjg z6X?g^LC^1|eL8WtW>VrccBx)qf;>&+<9q4()A{Q)J;BMVmyg2Yn-`q?N8zvy`SE>t z7%`AO#pa|u1`;+UTlN? z$L|w}>4Io>Xm~_G{xI)F>qAuddHi8Y7SixTHtQ28`67Sxk~^sN4lXxHcoX&mK9z)& zGI5DwBQ+c@(?lOl3bv{mV5vW4&D6oH?@$p!)jR`M!P$%9&j`%A?sgU8(B9WACB!6V zv0!>!xx;GG$bx>j=7;8vg3RfMYXh8xPI^H<9FQnL52$9B2}sJCfWng`IK^|qXXHA8 z{U`0<6hVL16(khfOJBUimT)BkSBh^5X7kgU7{gN)`#yh-3DKUvN+@>o!Cl(lwtkV{7zgDNDUM&OS}{`TXysp-XqX@U+s-@-Xld z%3FU?(1soV5*xXO1AA1Pr;E_>3waKDkNFtSj|yV~Y-1(yygbTEHaz)mM`8qI$&#PnU*0Fh)vJ7{&qeU1!CO$Qid1?5Sd1vlKB}FH3V8eHL?sAZ&*vn+4{UNyTAcAh5Xg#TR zpU#zdb>O42lg!3O-Z4-KbUmzSBimC^1pG~V1-%q@8140sbJM|TuvRI=Pd~qVFYM!w z_78uWh#&xsxSRBWb+gza+WWp?1GQf!7_r!(XHm5jV- zx9XDa24BxC*fcuRSkr2#7)Me`+|!-PZWzkM^Hk35?4?Vz$_BbB^rWs9%lt@-4R7SR zlS(!fu)*&mvP7c;vSKNQ6nu&s4w-^Zo^g?++{Hi4CILWC=c>+<#(A1nvq{Pgj zxP7bBPS`_oPFh)c?IZ(}+fk5(*G`(l2~9!11sTivBVTy$v^|X1^)w0V%8dQZM1yvc zRQk@G1ak-Tyg#S8-XLIadR0&9bV$zDTu2~L(;y?be9e4<%E1a4I@*6f6hycRkk*>C^`Ol^h6{KuC;fq33EK5M{E^(ceLz-=X$JqS?HO za)l?gz>QD0EXnxg)ZFE~bbRx#4us)0Ww7bWDKA7b?o;DbgC&2o6=fLcrz)?3U@B@% zWBd*2AWVHp2N5N&SIP*srwUi4$vq)m%o9uc)Zu`IGFylD71tzQfKSZ%1XtyJUt!_= zrc_MAcYW5DGxCRu$9bbZ>{-k(~gPR(TlxX$~(#k5X zjbc_(h(%Z%n3I2%bf`fYuy&>3NaGGJn^{hsG<12d)hdm}_)TIU*Za4Jv8@F;s{3f^ z&kf|!VT7vZhP&5<3>qR zG5Q-U8}t-(!tT0_sP^O-6#H|ZfYuVUp&WoT-`(~J)Gd&ZRrC>9a|xrB13>$rMOUrv zMy4!UU369}Y6q-2;Nt}3!y=qz4{j=u9~V{^8YPB;td(%ojV-58b8j(jK`S){!Og4X zW2vkTI+TCna7GT0(eF^&!y$vAGrN>=-?!^9{>}RfHDE3p-PXLO3>qG>jo$3oB+8fL zAJ%R8no$Di5K!7ANQto=UXjW_&J7}ZPhoU%D)ylH1po%=z8W^Bmq@ zPm*<|`<~h9zR>JYsEq-obL)2UNYL3~kgr^`UL-#XZ9q{m1Y)iu3goXS+zW_>!^pr^ zm4ZObRYL&+h-q1`-kBywLe_CLx*08vMY2liL>Fi|$bXo-12iBz43YseKS35w03%^X zQrv$PJbYjb80Z{DQbWpji~$clD}Q61rPqh&=Ege1h61%gch`BKqcC~M3Ln3D_a3l$ z<%9IQ;^Oeq)`*-dmq0fMGrB^g)>j68POO;IiUP)Jth+%gVE-LHu%iyG3`Ps)kwIxi zMw`>zg-KdymMtl=ekz6yD-`~)OqY)2nT>xh0?!VdvQA|v*=GDK<&>sh>0hH%GvV0N zW!WX=JhiLM>F9`?+g;4}98@pA;_9Bt=1U5RAfs={9gL_zM+9>#L2Bi}c!TWFp-lr! z`JLB{l4ul-U_GbQ$>6b_44(7r*GW9JIK)$H^qd0^L`{raOlUsG{>j$bd|z`GFmr!v zOW=i`!U0E4BZN7G-V^K60Rwf_2$MpVGnUV=cg~dxshv7)nD8&mv(ryBp){xgT9wYo z@C~wvE1OnV=H=ykD3pl^M_OrA3$2^9RozRH$vrMq%X8Q05WX&V&DCyKIg9wHvl(>h zXv=~4dd!5;Bnkkd15fA_3^woTgpq$vZe&(4%dwqla^3x2`UPx`WnWJ|W^Z*$vn;Io zDzTk*c!x)TP_Zafib=0{guv*7ukqBTuqGNNs&`IzZ4Q&={QGtws#xWJgg_d~`M1x4CGE*(A0F_+NJs5je;H1?R10RwrQFlonJ zbJ!z{)E;hlWIqC3K_<1)us_!%B8KlO_Sa)D%JIXwoFR25XHRL^dZdA6${tu@%G7;| zpdqoR!XkOT7-$L;;J@wZ=?#AnO@f4&vSty45oN-srqc+I^NEY}aYCL9HoogI*!bO8 zp~|u$G1sf%oDTYuz8flD`etgS(s-0t+*v1O(9^E#b!r*qB^k=t)ry@N=u&L6Gx~MP zJreFZsc=QygiEosOD(*Fzi`7W#MoTg@KJ}pw1K>Wt_}dkCQGR9iO5{E{o!RgQv`KEJ*Z3;0!n0xe?ak{?3odPPdU87JRi=>b3d)s&yj+3RA73rSo$ z)?!<^hqPsjRcdxrmnmusGVg6n(Huaeq=h9{M7%bgUiz34b*#m(B6GYOv+86+emV`A zbjSh!(--PN}Z3l(xXTS~~I`j2eiJ>xB1dFbyM2g51BJO2=wl7C9 zEblrDlscRTv19n5oxj*wWs41#C$TMDS-#D-=-183hbHzauh4sGWs2wO6kzx)>k1+P zm!hTcyqw?PAYfroqcdaz3kC#|I2`XJAWH@W<~4lnC=_4jaqxe3DY74DfYina?BV2u zz7kcwI@FC$KS2k3IsN)a7xAE#ayJpFI1l-JHxQ|~X%;!L9NwmI>xoc3Q9M$5WKIB4 zFMU=k)xoX|{jZCz11FVIlQtJ9kC~y4f-F(a4G)Ik!4WPdeYmRlwYo$B)k( zl(tTSO~NyupJRWvj2(4O0=T=9BDAq5DVXb?R%rYpoeAcEU^3at!vQTsm(YYbICEtR zNS|W=7C9e+b25NMbd`G_V%pW1gE7c2!4T%3WpF$}0B?Q#8?pz?D&;^i4Wyj&6C&`f zl!K}TEiYQg2M+>ah`mDx%ELx!nk7ECe7vJ$=*^b`WR8Ckr0s>L1Ec;96=fzvoMJGSQ=LnsFC=ipzTnch}9DX2a>LCW&@4sWf6N1ATpwQdJNxC`duiein^U<5Imws?A#u_UY~P$9 z%;bE$0L6bfQl1FG;*AV&tg0i!6u|})W+ww2bjd@jY7LjkCsN^dt(I|tehs*^zK{OF zbg&ABi@g}TH5;HvZFMsnJ~vr`C{+dYr$rtHAR4u)ax!`6y6$8wR)PwviLt+}%ncrL zwrY-+4~@&urFNYwM2tKg7$_E3mif)#PYJzPYCL~UV}N2Mh#D&dUFvc42T#*fW6Zj= zY&?qLNh#?IiCEX1VXInh5vQTJ)^ph-Ip-{Sb!IKF%@_J@?(RAVl}-GhY~)y7`ZDGl zCVyi-wa2=xRhfwDxs$IXh%!?2!Pl9JB1tkJ;Z$mbXHf~2y zaxi;PredPH-jb6Xq_IH;RZeCpCpie@3TA)7IzioJ+6Iw?N31raB-iqQ-mw$MwoZLv z!7)s4s^_vW89}x>rE6kPVo`H!H^4OT(REs!u&}x2h-w7Cvm6rSJ32#eEC(31ApCfL zJqFBxtAm45UtzYYFVt47nWrk0n!;tS6u!93PU(|`@T67HrM&!n-F%awV?&}Z2{?a= zwxFTr>Y3cU+p_Io8(C2LOX#Nz3f3l?#6nc3nkZPgmlM<+j=d>SYn8#8b(#KdHX#Qpg_> z1QP=H%oSzfQ&siyVV+m%Ks4GBwg)BXu-cHT_uj&(h?&{WR8R{Ek+!LV?d44;`(?T* z4YCM9pjVp`7^d*BkCi+;6FaNKt%Na33bH&O%xw%Z5~u|-oC_r!D`aGG=^KA;U9b)~lO4 z09h3iyuSlR+zkz*1_yk3yi$Me?;2u`Cia7*q)654X+mc-BuV;WtA@T==>&W^t;nDj zYl=lGR7`O2%I++wK&6B$3bI^MjIFY|qeaLQm0ICy6qk{JLXoUu1FhZP#0Z|dF@mL1 zDF9*DodS22$^yElRK}d!=MAM2Z3Rb1vr;PAVd0VF(4Oa8jxz5f)1!Z*&KpGAI#p3O z$DG2Grp!Wkx~LUsNY!B5Nr;KxYzT*|6zW*FNvLf1zsJfGyLan3fj+>fNVjj7hpzYOS~iEQ5_xBLD33UiHHlC)R&OxGASb!OB*Fht?6O z4cFdEXX=zIel2UvR;fEvcj11$h54~Ba~N;#EH>D1Kvd$+VoQt1N6pREmQEec$^L2& z9EToHD>lnkRHVtZpkMkYbNX2ew>2=~ZHT+RO#>^TyKX&mR-f2$>v1}m#kK?m%%RVg zAKYU93LF0d(+uWOY9@%Q&U%i2J1*yserR%-qiQ>xxDjW$E1+uFY}$EOeA6u6+(aRh0L@#6tKavlZ9qs(77qP z!x}Ik8_)Ka5bJzN$AZpS0Gr-JO-YfdM= zD4fI5r&Hl-Q8|Y@kmQ1bq(XX&5;}lp)1XYh#o-$Mn(^tbd{vPkMniGDEnQ^P&so1( zQjHPP-{##+zBG(^?l>}Wdz}Q7?so2Y)q;8b=nXlfzfKnigUET+wDhT(Re_52ss3pW zHe-LmF<5rE%E1oT;n3NZIoNicgDp)clT2FJO2Q6hte6N93nA4`61LFt&`fnZyOD$~ zEEtCtW^E$>+|;S?B2`q7H0mQ;Vjhftf6mZ5xh3XN{`zVS*K!`Dg*VkQF0k(bl^~P4 z*dI&>EDltvv<-<+J8pE`OhPuZS>#}2opXOrH}NV78yK~-oX%#Egv}Lb{@9BGkgekr z=vC#s-q2-+>ZF!QU4OJZ=RYh2GLIgBWgyg@?XDPz3t!R6FF*g!e2Xi*MBxn^T!C-` z)#uIz$M8CLX0XAhhBoXHdmsQgE@bR zimDd{5Z!Y)LYn{QU zz9xy(l8U{zlJ2E=D)rQ|7QoWI6g+(eUY8aI3&-&=wLn;LyekM*k0VEf%SG} zHKVzY2akzjDU52nw3m!d&OJhmyCJ5=-NH>HAALn1#kGM4C;%5<%#IyUGl# zL=gS@EXO+cY~qK)RR!s>Pm{La304LwZ?+RU{rR*8@xs>YM`+mOFWK9pe!t)IuO3ZMufq zc4K;&6~e2TEgVqje3j4+97Yd}@m^FZNUA2vF&c?w#rJW%eiE!LO!z=7?8 zOr(Tb9jL>znmQ;Ecq@OwjtBu2B?Q4rkc}JNSU6BlpcWg;x zjXqgdkBLuKN$K&c6x9;4D3mj|CPC5&b7w^qR^CICWq(D`H{{S^b8AJg)DY*gzapc+ z7--H;)W|h5)!W?Q_9(V6E&B$y$CB=cu2`$M<{=1)n0yuJAg@su?c4P@+&a!&(&C8CRm^|O;D(HhJ^`4qz|RHir-*$ zLA+W86AqQ;ySKSwQMYYGc8=bG>m_Zv$qRdfn;mv(ZqqH&#dnkpI^bM}8#y>qjsp_*#IN^IoMoL?nP zBm64N%#{&|0k|93LW@uZiP6EcY<02`Wzu@Tg@cX6C$ zl~TRQGUJCt`;uC5xn4_WZVDA%M-i?g3&j;LO%#uofZ7T{p4GlZ)mf7Z*cs&{b#Up* z!fFG6mQ7by^)=z;etPH9StOvS)SL=#0gQ?(}tm#TTZCA3DS_#Db!&#x@=z&JR8eEjwF0=E#o zMSX#GCV7;#Cl;o*Cf;@;X`k!Eh!RtYDS0h)HB7S5C>Jab^&Yp%9-vbwbfVRk0*VC; z{QZB~;OTWiSL|Y_9#+Hepog*(p<~fhQjW1HJ!V+Ioq8M*;m0pmUtkP+9 zJQhzt_U@&&n0@3Lv|VKg>MT*zeZp3ucYuFL*A$9&q%h0Lw3TSD42XC4__DCMJ4^E7 z87C&1mi;i*CJy7Jz<*g@@wzFf(s*{t!}&nPu|EI38PstlG05fuW`@iWfDk)Z9e3jgNa>cW4} z2IRxL_ppnXB?SOGpu1Pt*)H*e0VLDM(1877+zmm1BjkbrtI|7oi9kKMx%{!=#+v@h z`C$zKN+laL94yE=BPi6W8V&=Mq#;K<^JnV20K2RTYe-u=sWJ~+-I!jczcHh{Rg>>0 zHRkEc;M>e#6$}eK88WnG!n!>Koy>naffY?N=Q)Ksvq~2pON7uO+$v}NZWYpCq@iak z*z8*h7REY_1^yI3_gs8fPRLj~tF^}x7$BBbBT%cfG#&COIPg&8whVlf!Is5djNPh} zg(Zlb*UfYmH_?M07o5YLrTt~$@HJ6y9QD^HS&)Plm$a0OR0Yg23-Uxfv~<$G6_I|R4K}Xg+W(Wyw<1{@5-{XimtJx zrayr0i&w>m_lg!!XBxTU8&}c6_Uu*O3Qvc3jK;p6i<&DZ=aJ9lK${BWqq*MaT?&hZ zVBD-&lht7eOaMSp47RNmcIz+%=zj)TJYD(jwYqt3{X0@~ZHR`dxIBM^v2QyBF+2)% zog|uG+xnJcL#UiEA<4j3N*5mHMFpS)S!-RWOV?1pS=`sgL(U2T`MZSz-~-F5df8F{ z@OTnk!5sxa9vmJKsD%RHS-6U&Ln}oX7pOBjC9ViFpKMCE!7! z=Aj!hqw0w5?onG0ikN>aEB>@6ZO{vm0txAw@0}yK7IaFn*}>P<_QZRA@Kx?=dHPj{ zB61!~6KVE}?8uO8Pi7P3!FP+RnZQ8ht{j?QBsJjeNU{X@^8jE#pTB%hV0AlJE+p(D zp%+J1ZMey|fLTl*zZ8;AKM1dvUI3~L5G@j*QN@*@j1)szBs-|c*~+zlTj+}#HkS;8 zNB8!Qx~NrPg#@Rolm)D_xKDyu0ZoE6P)_5|3on%igI!mHTJQ=h(PF22a8X7cIP<*) zap=vrcNPT8t&SF?&nLYM=?Y~ZEB8H92jlYA8Y*T(GWhl?VxFghA$M1?AClmh9i?u~ zM7VH4?VW{J=yCkMQ4b zA7C%T*8Jb_)#tZfth%yJf&+zId-e0}K z)bI}EP+Po|U?Lo%wC)hf^)3X|jGy;bDviI`;7&?H(Fhk1TadF%O<{wj@vRNpPWx$bH$pP(^C zTaVG-+@2_B-oNuT8fc!&{vy1Ts4i-h#Mf03lbku$?_ zR6WziCJifHWA9Ul$uaBzp>V<$=bo_7Gz;@m@S8kuQ~bJSSl+taT>agl z2duYWTv5DrVmbK`9PuIKk%WJB2sOP*z5~gK??5%agV`B>d!Ky=lJr|*IoyxRp31Of zIgY*wO{cLirr|47mIhKovQd2k%+pMpN;R7*Bj!3|QBJnIsgxRW#0zBwxhrCqT$QQn z+iZQP{a-MT@{YP(2@~L0rVV zfLfL4jK5}ob);gCE*0$0Lr-)aehKtEeTFgMsCDvz7ceR;)wy^YIo{lMm>>WU8K)9jf_H`7hHrRtzJXBq)+t64*TiUN{t~vLJKT9^nfhGo zzW)yw-AKNdvGf8H0x~(5!2|^-1U4`;G?!sG1{Hrj$&O^Xargd;I(EZoiVW^RsesO@ zDFeD0o|~kDVaYzobMQs}eRB&kg5+CLH86ZAROWkJBZ9F9Q@;G?i+uU#FS7lA{PN{@ zAIiQ&5gj=5^2>jGQR#(zQ7^#?spE_HR)9`#etr4ltCZGA>16t^^5?hj5MJvS2U4n^ zq%?ow?YmJXJ=MOwk@&>L^zSdizm03Q)~cc2~0pl{!`0R#)+HxGXeC{RI|fvSyS?R5EuJ&v}QpTS3OrR#VZ z9c2LsedBNf+-HRecBHtdQ{N{j9N9x{H8uooi{1>3nRmM2LXN7Er1ANQ`Ke(h;%eZ= zsw-eL0bGBw!=_b2LqCc*OzqHy(FlZ!5hUL9?58p$9()`+dI8G3c&&ww3Wxs5v&MhF z`!KL$5lW_q#?8Iq2c14G3d#{3i#TFA%0v;uvKo5aArxqby0LOn2PD;pt7Hg4Uoi!w zz&hY51-3Z>$DS##&X&o#kU3Ob*QeWo!!mFp%hn;Eo%Xz)6W^!E-^fO$rRt9c+=P)0 zaE$^XAu`~8{p+_gd>G|~b796uq56M%io&4ex&_WAIYVJs3TMLt*bFg+Y`P1C0~p>E>|0__|4kU|59-*6fsEWTbLI7n zX7#M0)F*psM$SuVWq)Me-M`t?UbQxlv57*p?|rT;Z!;H&^?&*9`WU&tKVH|Bo?%zQ^>znnBTktci$2OxZ_&TM~9R;FHwE%%^L zZxBsXoM^U~bzV5#&m~#~brr~kieXbZTf=I##@YrSl&{^f>NsEQRzl_3AH=LW;_DxE zZ2h2?DjfyIH!70#X{L-yt(A#-U_2d_qJvovIMfvzP7KgX`;W3=-g{xgp%}wIuGz4a zNhP!Mc$5umZEmpP+UkGSG1b~$>Sc9Kpks5u+g0^!?atNQim{GgLzr$I^!ofD?GvTv zV1bu<`7;Z4d+o?+pD>7s+i_SeJyY%dsgiq+y3+ZS!&bF$w(F~Uz0T}^E9=FbX@)y% z#y9^F?zwQQ3)mbR0Dk2yr|N!iLK#Dm_x11R+J4kRYTn~g*|&cZlICn#r*mE3N-vD_ z6IC@%Hu+ziN-CW4o%GyWKqa?0 zL7GbN3}{7i$v1y%iC5P^-G7^}O1IvBpdeiOPF8~8))L*Zodq#h=i`1^F-wrn(?MyXs*;G6@ z=D4uFWElSW0Tj%BLf8sCz<0^F1LUwjB@~x6M^K z+z$Otio}n)>m^Y0^{pwojROH{HOM{68H6}3q$q#su=sBw9B5R-_$!@`klNQ$s2=Dd}fl}&3QDj0}DFko%)B&idd#Zl>RP+NN3NW7S=OPvdT8ogHP9Uh( z=OTY_Z*7@*^OYhk^<#Lph8L{aj0&Y4ilSW7>vke~9W3hwN(8W}mlPi6nD$l>C`b%RYQDDL zpZd5G|4IVD@GkmPb|@Xv!(}@jmOP|Wpg1qIbvlj0aVqWqM56z{tOGE zGh#o~^GWDH?12mD$}0d53#kRB2IK(aNrURe`B zBq7nM1YLYE+tT&Py-ZP{W^ny>q)io9g)!U7w*Hzn-0T9a>!nWGSv@tNnWKNF&vM5O zF>otZ?29I~xV8^~dE|p^pguu`-uNI9&bOlqNC937?fn#0*fP%u#e>g!{L{DZ;N(S| zK*^9a$H00v_1j3Mc~#SRPAcU-gD^l>)eCIFBxs0dPU7-*IF^YL5UPFFd`nr$2;nS7 zP!g+4elZ>%9pbX3TQ0;93Cn*#c3Y#<=Noz!l&1%UE+2iHay=;hyzjV*4I=w)BhR0NRSEfOpB~0pQ|1fX!;Qp5e5y z$lLr`sS?rJ96wu6u$F1*Jx{$Sl_hj1pcZ`7Otg1unZ9X-WbSQinV5f{M!{ShqL23d zJfjjW^D)vvRKW8Q}-$d;ZD$0>M*B(HP<9Lf3Au%#FjGxV4t({w-yhFh2V z=W)CW;6BFpq9hcb@0#o*dwYa@QtQ`6Vk$OX31x+K2@C`}V$se0Z)S7~8hEL(qILzR=8Xp!mJDac)l zxJ(l3ETlB1@-P*SM6`dy8I^7eA5hTY%mD3YL zDR^W1*{oyEWN;)E5Bw>?;yWEe{@@i}8%8!Zw9_@e)QzJ!D|74^J?;#;?B7vL~d%9cZCrx1Lt zta@NtM%*Sz#D>433s6rKvSTY54!fJ%$^oL?!2uA)4Fxp!2)it8iw1kmD=+4}RW!tH zsY&0yg~>Fq;m}jQrz`18ogZ1|1%^P?yiUHcqfCF0v8c|=Y~y#eAnw5hzq>GaqZU5d zX>_?)r$8k(kUGdTn!R@l(guT?Hh7Tf-mnZYpPX*Z+M-Zm$=@jb+j7VQ?^6OZIG9Jy zvA>}ua09LSVC6{n?$#!Rc%$;=m`0Rv(XypnKpkXEs$O2b7fCvEuv_(FL<~v;rz)aK@7qvq18g{BZp`cUD}3jBm=Qp@{K%( z8D#t4oES%A?SnT*34{=wu(8+F9~m&;wWfc0ywy_?S!Kl%0M(x^l2tit-YK@o9va${ zjEYi(gcK>#shbF9A5M%;B;%CN@%vL6%VHv-g?IVODS?4f!txG(JKYB;f3OR8c=)3` z*u~!W2}XGDc^6t?u-|)*zDl!4$x-Hx6-KL>)QTg{)o9B|=|t+SshM(io1goDo6NszTsfxR9G^3*O{iTcPgo@65T9&Ye0WQbB$5oPTTMgja3>)0rBkLodo> zYS`vzK2xlcHPtW?(>bR$*}m}lfMoXtE>?@EVWz(ePHmEXZH?Wp?Vz09YoVl{0oy7Y zYZ}MAQ$&WIL+?4>6xFTDEF{p-oP5Vp|$gS z4j%4sa4Qm{VGF$C;2|bGAwj_>lCtIw_frWs1}vZD^;@o%zT!R-*i)^snao);aHt1y4ILFq1rLmesp2>f*0GrUK z;FiW}qR^0M@reVNTN-OxkPRzf(UZ>Z>Zn`q4p|vKop%CS*ew4jSk6f^OAg2^+R2jB zbAvRqC?oNbhBmixS4@89K!Q?B^txqq4F{y?)KQ9OSjQ*kxo856>1kCXGT) z5WSEa`LIX5hv)%2&(5DLzBzwf#_=28)a@xY^-h}W+hQ=qL{XT)r*of`4VBB2gyG^Jy> zRmyUqo)o*svt@q$w{z~BJ)%m@JDcjwj*~62f@}8^9vK{o@Uvj2T}twiyGpi53aObU z!y~Wk5(T~Ug0(W_#Z4oZ#^bPr`5MT*6)sRLjz><5+Y zyTU;GI___5`#CKg%h-PkOYP9g@K}Pg!Dt;#lBeMoterBWb@xMG2HK3G{@eO3jHA;- zIda@nNb;s6GHA3TeaqSd(gNqBsr3Zv^?thd^IHiOD+lc5G4)PHGB(14rrC}@B^Vio zG1mi5YGUt=Hw{8T^{g9#ti2 zado6pS>IRRK`1ekq~COknH7DF7>dWMYFaznR)^(0SdL#W{ZKoEk8p!^wDq_ub(@&b zAu%Twc=yI?2=<3Fd!WXZN{p}QNa{)WJ(uz5N`oU$9OH;avMi%`S=YvN+REtY|&tZNp?NQLS-sNo%lgBxQ|o@>aZHLi?En=0!p>} ztL5U%@Yua~@jRDyM`KAfkK=w1q9T9SZjqqQk;4uT8dc+&GPN(3VY%M7M-mUlW_Lk2 zdaTF$`4SQB%)Q%s+|17ElQX52(Yjlz3ElScq0;WW477hNnQv_!_*(ZX*HBcE6GlGC zKCei5EhNxLB#J1iF4rogB_{$fPZyDlz<~xZd`DH1G1e$}{q$|E+0Pt-ZRbj#HBuNA zCIE~AEltD)N^Cb(gzP|anY?;jRx!%+X>+|@7RSMH(VCuF`2>0M>6=MIb*Akge{jWU zvdFzMtVe(5y;9%2e2AlL?|oBFCF^0NVKBDb9pHxN>C@_d)cW9+GV4vm>VpbwdfC|j ztqcU8b#~1*eq~|#AQI2vU2aK1NYc+kn4vt(+noqn61?=jz5xRjyrg$z0mH@D~xAqGcg&*cdy5}bxrHu*ZwK*dd`1E$dAZsFO7aDte&@bQnaz-e4$6< zG(9h2uHv}5y>Y$HPyas#wz27GMEwM?jg7)(EtWysu)+mLVwko&Xi4FS)BDhp5;luR zn^-T5YaH#J`i@*dt40l1)hTEotS7e~dYhC^BUm=lMMyz`6kbF6pMVndosfb8E0lI+ z7UzHM9p`Xvnmwe`7R`fiui8NR^mh)-_AaD_W{tT^vqoRvlEklL(x0!bO^{O)p8k3n zhR$KP34&E(x|v6qLarTMfyac6YfJ4qlRjZ z{3Ru6!*r~ii-+oyBfGDT(jygevioXh#6=sb!C1>z+AG00QoaOww=*y~*G!YGbv1Jj zid>4E=!JnINk=U=hFb#(Nti=7U|o5RVQKkF;XZXV!iq@v8*NuN@w6*J$ zGj7Ig^Y1F)vW9$Nu*~{^mGZa6fblgcVS@pX+YUKl%SPHES>0NjZguZ5XJt-io2mHF zwHI>0*4{TtQR)E6c8eq1ElDZIQO@J>Rdw)BxK3+pu6pOuh|AJj+li5Z$t+oYn9D1*-r|4wtd?0uuo=ml0(JC;~V!mr)N17Jt1xOK&DO za`*WaI@&O%mn^;kt$_JPR)9q=!TPqlr`X8=juGUt{`;xon{2YlmYf_kBXu{si^XES ztH_@I^NBtE%O@89fBf|6Pj6g3xx;DD^697l_{8xBd*V-49Za|3`KYscPPF?EJ)WNYs za@oxNyT|u&hR}ia*K2SuUU+As8IOD1ZMEL$_!Mi$lgs zBA7cAN!M0-;ogwQ2+*t$bPOKtuBt))43QsISu6 zDf#l*lMRwl_yr!3j@~k*sqh6A>4g4=>ou2#A7HyR|0S&;8(~M{qYen6_MkiU0!lIb zh=oIOXg~7j?=RtU5`ULKjo})9MImKLYbIZDSDRgn1B?qJe!hguA~9*xj`;Qa&w`gP z4S{obO?F@UJCepFc%12j(_X1Z{c=f(oU=nS(F`HV&_oT$qXbcmwiVrR)$*uBWq8}r zZ5_!LA`|gU$6pnuFdh2I3=Sd#;%da)^4Rb}BKGvGGy?_~o_}|NoK*q2fe>g)0^fG6r&7fa z0hzfpP)ZU#^uqjN7NC|j>+qtZ6tQ#8e0&UgU@KI6L9$nfoyTxd9lR{>L|) zF98IP0~#wKgMS>pLQi>o__sDv(_aaEvz4Bvm!AGfk6D)?dMh(1sHrd;ufQV_Uqn>o znI6UpKRW&ZlA=_$(ghNZXhfMK-9h|Z@;1v3W1IE-?w{8z7fHYo+fgV{h1=q}jvrc@ z_AA#sml!Ba;2Luq#Y|v_Eom-fPNHYw4x!zSKz1lUoPWj<=CFHehBN;C7J=K)FgOzk z3U5Gq_KeBXTAql&BTkb`-xx zgaX`)CqztmN43I%&%l@;UE4(B;4LXFO(MjfhY=+acUwjg;!n#H!G@jVg?%)h%T)M@ z;lOiISG-~S+Om+Mw50Lyh?^m7ze{!?(fH}{u#m)3BL`6vIvRfkg`?9QMZA3f8H`!+ z9)E2PeWDAtytC|yO>uRgzLZ62RDVI+PWkdbQH@HZ zPGk<+RjfYzb%P;sqtPU9;aH%XqnV1lxd)x_4VFjgnD}>?NKLE(#PQV9-7GJowprfY zJ|`cwmYnX`0K@030LPbhA|PBP+bQ0MxPNa%5ySZ0C4(^TFswzzcYnR!?r0h_BJ&n| z$zGV@D{0W4Yw2Qv1QM{>tV!}QsrN9Zkh!bG1Xsz9Vv5?JLK}L++;;dR=go*{04I|6 z-We;WGfj7k1r$mA5o{%!G#~#|mh!gt2PSq`7IiF|II=rZjO+P9+W#;fq7NXJ(SJ_R zbKkEompUo9LpvIYn~J#|2M!2*C?Q(-en3X4^iqPNs8O;9Gi-{1*VW^4qIVUq0K65n zCzM|(Y`sucuMr&2c6Vnj#E`QhONOhJs?^|(wKzmD_AW*IAJh~IE_6pY=l`7G{ zX=AT&BM;4KBs-9MZTa~uxzT0+vFv4%u3rV^y&i-@oQtuoMUvF1;Ps&K_KIUQZ%>{Y z4SgIUJ=u6)JRBcl)A%}6i)_2d*XR<4ba``H<>VH1A|oe(*!tJpLJ!TRY=4;ETT&F_ zG|hAIlVy^Eyk4Unff86bF$i{i7R+_Zh+rpE-9IxmE%RDG^5B7HBDkn`HapQ2XV0B& z!WthTySaVAfR|A9`dzxgj?&$||i7F2#=Q<;cb~5qmqo z66}!Kqb6_eJWj5|_RXuE2Lcs-Bn;FlmDq8!lHbNE)q`ImFU1Le4Sy^e;rMV1?C%Q= zQG1tB|LM1~%9%f(LRaC+r4G-xba?+%wh$}Xn|*J#;=pftM9u2?Nx$;2ZcBDQe#S{g zdr1YFt27KxVN5)4o0A+Z4^85?de?&OaE@wO|8Y+#%$?++*ry$?j1N^bp!|MG=o~d( zet&|0MsDmZ4#X9?`MXPUW6%g=aV@K?MSBQmzi8Injr_EC%pYU#x^|54O4eKckF1pZp7h@)*H1rmwrSK7SBcq|Nb zMQKmA&ROg1)$EL)pp!lZ>nUyADoQl*Q9H{Nl5Q+k=X#p+*?$@Jr1K`4s87}&#&kn| z`2IQ{$sU$?_UJ3)ttyy400GbvcexZh+MwXz{Z`Fa{?0&NIz|Kl!e;tq-!S%sKoB*O zzeHVEYQ?#UFyZ2hX0 zNCA{Wq~o+-pMQFZJT!YUy+q%x{c;m08#|ofJzQH(HhBm|Bbj&8Z8_N(+9bNg+YjG= z=6301lel;|q64#1KEITpuvfWH36G~tn{xnTsCub=hFvK*0{W-(+h5B!a~PYIIIdU8 zsxRk-9g+AjacD&J9BnUNSVbZ8&%!p6z}nmU(_ZdRdw=Oi4}&+XM-b*fL#LTZ-gBCd ziN+j;>(S(kq4@IIcngmx$%n;prLvnSrvW_tycMrjGd^9>O1MIQmCf2BLuN|@k)cv5 z5IIF~ynj0(REAV8F?#al(me{ezf?cp%;D_aj0Hu;p=?pU2vKT&2x2E_pUFPMb}R!W znxKZ<0)O>amL3sl%!#lUJcKeq8T8m87NWf`Nq%jT^+vmhp`ogwaXUkaaplBWA5?1` zj}|)P%T~r$;x2NQqGI{bwGSs}H*fL({+jz zIkW`%9~fF%ddq&N)Fg5`w`)*{o8KdDAw&>-^?y9CiCYMFaIz#(`Xl{qrH`ZBGUQ!v zp@z4L9Trx|pKJ3hE%7kl%Qkr!`MI0Q^S^!UU7vjuMZVtyJJsf^FrTwK;JtJNEl9Hya4I z%Kux^X-A%1xlyPfY>W9t`iw#R!3ilrVfCKhw~~`ss(OYLZ;?|enD{C#%@o{l+{)$+ zE5|UGhrzw7P*_T}#mgz~$x-c4R+9FyXV%!1ca;^c-Jx|i*K2-Gp-)S2 zn?r5p>ROJZ?nZ!TN0GI&U_`CzCaw7+u}DDf?LfCvzP9E;Thz;JKY_++W$i?_N!Cfx zO=9s`c50Q?YyC+zdfX6Uf2hTA(<7j8dpoD+88l`qM@Bc92==}$PHAI~o#5FC;(sI4 z7C&ocDyw>a|z37eHdzFDn-jWkJc!R}j7on7@E)!U!U?RDrve$sH zO2LGKcxp{n*TR6RGMJ=~p!{%hhkvQ2U5L|VD0yZn+^C4WE)U+dZ7DyFSRsHge&LL`MM zJQp+ZA>VtSf$B+;p#JfvPybU9f;dpXW>EkAw@-ij2j2M^fBy1>?8@1v-+%qHzdaFp z3@S_i_4LD1+x#7<*UERk!W~MzV_n7A=;urehA}?rC z4&|fBO0p_sC}n%ZGFz8XpT0D6g>eN37~OxTF2%&ELzNr}mFc;K6m90tA#$%{r% z{}p_wbN{J~LF(WOOBzMJ>3<`X*@qgS9s5xebm#E&IW!&K8<~Faw^d%s@E%mu3T{{$ z6IHkfNA%)FmLqcw!9?=_iJL^%xgtsFN?a@fnk;|NqH`|cQlGM$Gr~ndkYV-R;3jIp z4o=``rATk3u(KLxD*L$Pk;4fF*)0@*o;$p2_h+2pM7s;`O$)_OX@A+`xon$|D=#~_ z5uVv~^TszqQh_^yb2Ui~mzd+u176DdN~xzG$if7|&I#-}_>n0KG!@c|M=q#G^AXH+EH=*9nF|cnKr1j=QSllm$zn#43|$O;`aQ z`xm|{P^$L3XV>ndDsk%D4JiBE|J5e6+bredb5Mj_c_K$uCvVu= za{kGfYtt|nzkgYJ{qIuEl*%3w;H>_&!E?XMeD+bb5|@54R4=)({rgFTQHgTPyOOKP zi*W}Ge;?#vF zylET^#=GWJ<4~H6jAprb(_8Q1S~{7jvXkSb8qeQ-yMGMKlUuQdS7tf2%djpCE4JX2f)cN^ZDc%^g1pSFXu<0V z5OnQ2SbQW+gqo`qe{RJa9;Pl zo?g@sMSuDa4q%*QML2OtgN#gA{BY;#nM})p_eP+8e57U(-xmE)_#uoN&1$T^;?6si zGPVD9;@rMYg;R&I(7bH{DdoZ`fF6L5iD9Z%Osh{z>*LAIrx)QZr4Pwz?)+dHw(1_V zI)KX)v}&7TI8`UhdvH=r)lJ}>1a5Kt5p6g`_<#J^9d{y=2Y%@^HLvKizTjK9Q;P(D zh0=^mKcaLM9+gUy0`hg=r|{H>S=baqcWl_8kYAP6xF#_oKl`4NR^%vv%X4Gdq-2LB z!B#KZf*DEb6!Zb=l13cb+A)~3mQMUIQsEHl@djJ`2!{X-;SO~&wKX$KDFk*-UEKtG z_J8EN$w8B~*EJGI1ds$#(x`HRft>fFsh58oATyL3qZ&AJ#riBfOp#>KgI*Mbt`*Vi zBv-{Z2`i0qQj0I~+!nkxz17BzN!m`K-mj-`a9Ba~EM<#>e=ahfD1FTIIM{8Nsgb4I z$pu90m{NOiYg~D0sx$D@0jFzUWWt`N60E`U^6XGs)J={dD9H3>p}Faz7X8xLzCE}<_EHLTr2QfVSh(i z(9(yHdfXFh(t4k;D8Y=Xwi;-Ey@u9N8ruZgNo5UcLsr@oCeG(Oixs(91t7I6rreC^W>;t*)bYhijUgk2@;6i>}& zy;l7`OAaRm>-NFI_!NU?W-I+nQGat~K`slmrB#!9CYAJ+=zK4`jnd{p@DoLh8agU> zow(ccJyfZ*<8`YNujb~whZ}v^INAw{*i-e+l~qEG#~k1gg?7W15aL1|juxqfyyP6D zMkmpMTDnS$Httrs$5x44^NxV>z(u|@H)>GiXrb%5eY-AaqDlf3k=1%-;NY>W=X&Iy?R|0-}QIIm)MFp zrKnV0hwHC2@$?LHisC0>Qsv@as(;iw%|N>n|9Y+dp)$gi@IDG5wkTgxBX6s35|)&> zUzocEn-acf=nyt4!hakMp>Tq1hx~B8QKYtq;diG)r)~&wYdRKu;oF_*P#GbaY|V6F z!I=1=jO*u9)f4y32=yszP8l90d!!HH4;?-^cwdc6k=LP+Nj)*fG2dw=!$ypGlnS*Q zeGX=qtxMK7BhEReSl#Y|E`w~Z)?vYN$(gSEA;fZF#d4)U#ea;Q7X3QTED*vf+y0LW zGq*2>FRiGrk2wi>ha*l5+Dtfcc)sSu-rEbX@9m}5R+jS`(3R1ITBOjpWvREl)?2oQ z2Jcqy(5%kI9AQS6RhDtm?~7atNo~_~Gu>|s-?qhzx`$mCSeyRH=9ChX$0oyjH2m@^0U>5ET>-=ETE^mvg??H`N^=PT;<`c!L_~ zS>P?u3kbBsM@(i%@@aY_wX2j16*9G@Y zE}J3W{=7Jl08I_(s9|~Z6yP@F56ML! z`?{YjnIPTLEsjGV)k^brzbqJ+HU8MN4m}~yKW21V@m!;#4_fx}DWNbOyHzC&GTQO;emN zr;EQEaitDx=GHRP@gBI{?kqFKp2^SML3@!SbAMj?T64(z&j{ZfrBWTLvgfD`?VY`` zBB1NNLg(2)1I}`eP>Z>4fasLPsq*3 zPJEc&f$|E3ZSnQXwRkpw)>JoS-NKq$CxB^3EoN`^p_uDuU)eRh#zP{|a@>m<$e~cJ z#($ni_J*n3!aYj;akTW~nIKnZh2`K#{(iewt#WRzj(3c=&!sAP$5GG!suR*6rV2)% zW2*QWJL%34o=>d~dbdKj+Zs8>R8=v#U=ynPjHEwAUuAens#i(zi@f=b8RXs99{xBb zD3wq;!_ibl#tM}W$pU!*?tvQ7D_KCk3V+-H-P&wR0OpUc8GdlmJq>MkGN+p%>+Wf& zE;HcmD8B4QKUPf<(;g?D9A-Iz?1j9efF_9-5 z1hfWt#W98QX(i2&jnmw8SfqN?>MR=R^Fumh7VW(A6MEd#)yCl}A1?rOr}vptn}0iV zN}4nL1Hzor!jy#;0}G9anh}wZ^}QcqN0?K>v?a=}hb)D;6u2L{L5m$k+5e7@DBbJ9 z6XcDZFazQq?ka({m1?xSOZ)cHOCo&epnm1*pctfJM>4;KB8ZDBT{kx3j2S?Ud)$po z47F~*rflP-{&=q?qdnWZF?+Dm7k^~*Ymm%9C^M-kvwPbE%7uk;OmuyIcpnRfRg@7R=7xtY#M^vb(MRon1mCw=Owk4h4?|s-i zp^sclr`b$-t2mvQ7mkb$Z5eXtGd@^axYP$wry`2(w8`uAN)!Rcw8&UElz%ACPskP- z-?hMU_lHOATOFdLK@ z+VoQiN%^cg+*`iZEdfLNK4j-|NpMMxkuIB|33shf4>v41K}vg}|Gz^JsRJ6fya8Z& z7#SS}r+S!Y+Y)j%4?N2LN`L)g%H2d%SEj-Ht4ojY|Vbr}VdO?x~7c z=b4oJpaf-Yj>@b_*X3^6&Ws(WjP`z?A1nG#d7`InDA&6AMyU!FKT4#w1|thUkf9VE z%5%2|lWwnGSt5aoO#&K{o!J!TOFrhgn~+k*9N8PTM(Q(LfBAx+94 zH0|o2S{*xm?!BQKW3y6!q6(-*E?$P7YOZ3Mff9COnmrup%FPm#vGL_+-B zzGZc2$$z@4lF9_3TZC1DF!SC>&Lo{G((bBpk_0tMm(Yy(VX>(w7n8qpg=t4pO~{=| zIXcwm#+(r6{_LV=PO$LhNZ%Quo7Bt`(>e6!#o*4LTy$fyXg1^^(XbIfon6Nu54Sw?`MVQU35JIL(IdH1BZYFzzlNCTFNn)!4P&S8?cYh)7QHFA7s+e027k>mB(xMm|yDGovzqYK-%-0+hqDq6k|%)u1~&FDMrE5hA{C z@uW_o5AKBbZF#&;_Of763w7Cl2`3P;Q@knD5bSyIj!>q-pL-*H)Jp{Fn#f7rPJcSs z+SOSV9>#E%3REW!^zSVhkbMEV350;%qmX=nE|p%em{CqA|;j1IS#Tgx?NS0D85ONvV8fs z7y0tH-(>su_S?7Le=7SDMRefI%WwbsO{Ev|MZE+oq>eA%TLC(~`OC|n-lQ}^O7*Lh z4$@D2f7RNgr*Mkox`hOB>=}oQPfr%Z6Adl+Sd3(89M7|BfTfc7&56 z7|llf4seLx!sU$sa2&3``Q^BkU_@HssjWm1T0gUsm>x#MccP9vNkkXg`)78NXe}Z< zwG#tDn6TZ+UYLy5!Wo#Q$!1A#nPFpQ%(Ft(QeK%8;sm(x8C~dVZUq4zc^hPw=&eCcYv6;L`)#S2O_~g;t7fXrDVWS~IwR36=a{gB4}@`^<%%cPhq; zy3Qc~{O#L+bvUimN#&Ui=Rf`B+n@fN-u!d=`NK<+?-*YGr+oXD^y7pF`|_VJ|M2aP z(;PahCl?cf?Qss9m?@BLc#xyfe{v8c#Hq1r=VHT9S zIv1M#@mtn5S+dIPvaW#p%UaW@>WREt)yJd4qBFbpG=C`@Czkn|k}Rwm5xT0A(@z+4 z;y$X1#Ce-)EOS!LSm#Mj%fOAqG0mN6a8$^PJMxKtQ-uZjD$ZtEu-_X5)~- z+aMb{q4kX<+N+_sq5G_Utr8{z!{uFnEDC8d`jg13$j!`NfVA_%r`acpbx*WnoG|JY zRs6?)VEyqOaj7fw-I_ODejE4%>P=TpxMaUVksZ@1D~t_Y2T%}0d>aHU;FTxcHb!}J zFUq%9GSudtGzDL=Tja9N3K<$UeIsnbS6`4=##gj_;#ZgG4q;-?g6KA;v*YyL$)M)n z{g}DI?|;lJj>6t|>Zw@f`Ed@0m5Qf9uN}F6lLbsxu$z`nN`E3{3@1{Su?s1qZ;n%y z0R%D3`YNv52$w{uTF6G*qCo=PjWfe|lS!qJR18+K+D-=@_O;G%#!i>n&2Bvn!bylt zutP<#Vz5C}wfTpf_ zS5l&lM%$eAJ^sJ(ZX?{rAw2q>E=9ji*?WGc4x0F#&OYIHDxpk$Q+Q^<7Hn+Wwryu( z+nLz5|Jb%|+qP{^>||n3Zq7aD`|f?K-7nq!)V0^DS{0PBR^WH~ht$P4(%oH@G4>9TehDVdL1fFvf;#zQ&=K*_DHzTe%2DS{_E-`&i3nL5ir0I%L0_TQL7V$}Ek|^1Xb2 zjCFpfEXi?E)Ju!>^}UyTWPYY&ER1WAm<}R(T4*eiE^FdPGYpArq^<*I)AX_RIeofFY!p(UQ671T(q` zt&_knnAl3;bA-qv;fslZ>k!vr^NbAkvdWbz!j56FZd{@h(Dg#O6WI zIQFXQV{+mAj=8}sHi8`$gtxV5i6NuvotekgY@#V6H;xv-w0pL6E?doCQsAAV@FjgZ z!FAt;QQI{9EKj*PliNr27Dk~w>6jbXex7a~j*VMf*LDtS^-~ZMLQU2gd ztSBQ+3Gm#ivE0a%BTY-`yv5#5e0CWNuKMy4FUoE#o6k1-loubOVoaVAl}+^VAS*I# z9H*pbUPu9~ca%Qtd2?jtYN=YSkE){MzUiS8Jzn3%$gPJE>a@aW|AJ+k{Hb&Zw6xH| zHmtYcfIf)#1em$aEBgLzs!BLu(ZJrh55+a%#hc&JH>p(z@t->UKMcLb{qlx9fuL{JYV1+yq(BHjE9g+u-PTu z&TS>5(=p`U?#H_$IbZM%X(_z6B$}psxuTJKPu+OIC}xS#Ql{2m($B+gH&);7y~Fb9 zKWV%C^Vuty0k7!Wx$^hNxZHc1tdZ{CwuB>J>Y)5YlsP`_d!QQh=d#0zRaG1ntz_?$ zY>y2fCv1$cWEGZc9NUW13BAc*{iE?*Rr=8f;%<*=xpPo7HRIJ^e@~t-c)Ja9dWT7n zsx?>?nDE-6*#PoxD98XSG1KB9*v8690Jc?I_l{8CAM!XQLCC75{35@@$wwA>wF& zxmdVD@(8`rzPZF^H3R-fv5~AwraDpsR8hy z&IsMC*e*OBx#r;46#@;~cayTMPFUgViO!YMmJ;$;G9laD2k#J#N#u<|kPb>Y3^e`G z&7=;xu991mjqp^rsBKUzeV^*ei4qxCL>XuzA`ER5as;&j(@qX-|EW>4)xI`6$S`^P zuJ$C^&DW{oa)r5HZ4I~<#@WA0(;ra91ou>%r3QAwu_mDh+B>5lm5W?O>+aZ_Zplue z^DM26lYg0z)Ut5HU9u&QCc0hz#j}>U>?}i_6eRZ*)d62&d0aM4Y1pAtcB49PGBbh_ zE58uGcTO*B5t%zOi9kZv#xU#PD`V|{0b@Id<*|fzHNS)3iF0-fl}iHY;0Cbg`Ybw5 zLK;sCnVQa)z#mJ57zBlOmmunAE_d1zCTG@swN=Wd=jMnP@53@|w&0Psr^B%4A9Sn@ExJ;c6)RL)0 zw2XLK7hrs~2`y5D=hsBwnK69~hdo*G_Mp4oSq^NV{^W4;?iE(yG1Q5D0|S2xS7Ie7 zHL&&JZE7P?_sx#4H3hgAw>mA7$R69mytKB6T>r|v%y;wijz86_&}%cmde~dHWQsqi zjWbO0+8jBmL@$sNfY)6dpUA?bcx<$KIs9UuA;qQ5Fhfr0EhWS<0tWuXqtjQuKCbBO zp)C)5zUf4!WSH~9`_^AX*#R@lPYGY8=?l=7kcs@-j$7@8!Uw!=pCzoWvdwi|hwyUX zo${>SmxeH&J%SP-u6{q+HOF;;wh6%6SLK`ughbkeR#-!f3qw<__Hf)EBb}iE4=m2( z7p*2n|4e|SbW{w@G2Kf*6<&n%{dx|%36c5?Buxc}bY1boum8fa&=R{90P;+sg0x|x zuEmm6wi1XBD+kyHZ=A7TSI;|bsTxHSvz1gBQJ!P+m)oK!ecj8p?G{`+oLVs4Yk0M) zPUqcDZfslX*}r-9wLq9UP-54c-9ZRkrxq26tJ97Y@D8vVx-ET?w2%VWWDkO+KhSSM-Q~tlC#@E^tEZNF&P^+vkBM&F0TBoYA{< zm!^)6fd<$bed){X8jg`g-fn!b-nQBtvq+6SgRxgICV}4X;S_&K)q`&`xEOK0{#udf zWnfi0-ZldfFE)0}U>}qiVtye!%|fqM0KN{s+Uf|V-v~TXyVdAu*BKCnS$K+Nm5A>m z9**sB*2-MS?kK~6_K)z|5A=GH@p}_~kkPzyO#mFx6=^kq_TLaB{m?dGOT{>|1DUsR z)1P94imcD~$3qC%A~Y@>VPX{e+)Egh7LU|Mc^`qNXcdu3c4#&?)4ovfQF9})Il?m1 zFR*q^(>UOo;3!y-re6R2DOLq{leq#9Y11tX;@i?S^R`<~?&FAoP(UgjPMwTr!W*r+$G?)GI6fH?K$H zbGcozf};VJWoBJ@q#FfjDwxcluigAI&H&BpcfH?-7y1-bo_7cT0MWWZ`lVv0$=g3N z1JaloJL_om%wE20A6tL^v;NgOE!s3ha{y#(OhFsZir$S+A4E*HJks=P@c6Ww*B0?y zozmMn(W(9)ZCg!Hu%_Rnc$)?8y~!bacA|%Bemk&(ArSHCLV9`-%b1tKdp*`Jub~TN zOVd@*nELR2I;GQ;bvg5}3mfxDftYr+2Lv1Z>C%5RxoFbjl?OvCrY)l~pKS4C_y90i zsEG$5h;Te-B(?MA!(qhby=`3qr)Lg?{cmu9~g#o`(D%6a!Ji(FMH;!{{-6 z#eRqGeavkcB$Wh0w$NF$gmAYuL-*YL1>K`N&Ad=MLOA8B8a%zoCbh0i;sQs1+v>-( zaGsMlMj5DOpHk^VqabAD0?NH#t^q4?-cTA8C&;x*W90}<;7+lN)P1oL9*ZKqN=_~Q zeSAH6Z5hgPyvnDud~Tqdl^3HJiNk${+1C>TB6Br>%cKt1$rI zd`A6xJPQ_cOw0=%ogc${MMhc{*PSw{oNy95w(cJy$LUJ)!)fjohn;yoJW4bHZ^~=` z@b%4Xnl(;WS3w;-naG|%H|eAC$nGD5ZL-6s31h6D-ZPp#@Ut;jSKSr|SZ$EZi!3nZ zdF&Ep`WOzM`UHlPedivsAV7%zS-po}Y2auy7u^*>zheZ()8AJ$Jxl~BD&*-FSeEWX z+NhiJh}63#gEh)7-l0y3eJ!!fJyn6cvKIMFE_4v7fLUsRG!p`JfhArGwW55&}e-39tljYcbOR4wIPv>jcf zvy6RWgEPU7bK@<~ce$4*HR3Bwn0!%hSdw~AqFL)X+FH>n~@D{CT2&t|E0tbG)< z(x+@3X`~3bt+xhf;6{bpN1WFBUV>sgdQX>rHR>+r+HHq^Re&Ye1q76Mwd7@P^siCM zQ|4>^7q^|U(Z0yz44vlcM5M*+-8pj^gf%8_oG*x3o>m~25%LMpO zHj8!4S~$mn@n$oiesC9cj2|^Jc5y||diH4%57?AnMue27j3=my zctPLZ6wLrAGJq(K*5yfTf%+|^57Ba^YiY>derH`-66YQrDkAlO?OMsI1gYq)&WYXW z4o)G@0~*D>2{C~gtJu1$H*@n2If3gK?qT(*%eoo|l0caFUT)a6Tj%z99pgGvwDU22 zhzru>%w+W1(cOhW?X);J@!hpm&YmvU9;^|(Wp>GNEP(QN*-EfHPFQj!a=MIkS*lUx z&VVOl+ogtnOU@VBOInBHhkTv-S2j;`anI>cte2sTHu{5_e~sGRN(u(Fli_Hp^dGQj z-tn9E8ISH`s;x&eupJ$E@qpw$ToKS~(ON4ncT9m-ZX}3rNg_B69L=Dzkn}%hI*>`c zsxOV8^#Cu;{`wsZI+Zwta>GflldC5C5Ms2ai}mTntYypcXdoGS{FpxM-xc+2!Xe%x z29u0p@c7A9DuRm2LSQhPIYnZM+LE{%;SUo=vD7I}TkH&Eh96#Zvbzo4sa4Cq8n90vN|3yIGf?G1JER1 zx>~vdv@b8wM=LK2ME*o&C)(ysnUMx$8)riLWJ1<~G5L zj2FD`D#c=m+Ij0*3u11d@n?<6Yv=D9T%X)yLD zC;&!#$>p|Bd~klgAm*^0foe_a9pBkNzcphB;ly{5`(yr+Yz7$IKfY|BQ@|5P^J2BvEC(=y#IUd5SYxyF%Th z9oh6-*^=bXSJ9a^^9=$BleSt9`msT4!UFVG?u-~p!aJ9*5@A|;gbM_B_7sHMCI%Ga zT=vSVq}}OHD|Ji4uWPx6P=)xtD%ASg!yk=lT0&w=$K5b7*i~Em{*~yULIyq~tP}a& zX~5nKn)S}P=uQqVg@m?(=sZxVZwlpe(%n6izvK7B7Sb19a5zDN+y7qhM$(uqkYS4J z`>5X|p6Tyc7(r+_#d;FO%1iuB3hlPP`U`2cGwoLVc=#xlM0FksL_^*BWr{2ovSN1_DR={@B$5j*xp(a_JNL`p1GR{fXC7T<37HX zKoN^n=ITD^v3uDn z`!e>fYBX2E`}|~vHf{fVx;OsEiRvddSr_>Dba*_a*F|0fmQJf3=$4Vzn|WluHjI;x&#b@`BEG717d>yi0beK@bysF~IPsh+W zNe^3VlQQiGY?qb|O_IIiD;pd&FxbI~%T4HpOE-LgmFB}cmtN_V`?nJpO4X)8)DzHr z<$})r>A{BC3YNa4-ldy2Z&O(>)Tr7)idsG6v4=$qfT)*Vb@|0E-3F4zDXNqkTc&tt zrL)>IZYAq(B>WkT=K5+FZfx9`4d##DttnD@>2X`@dV82!>)%OR{lcF zpQdeqGwH16h^Ix?6}%b;;w7dr>mf?kVC`$lC@q@T?;FpBT6Z~X|AgJVfA4xaMs8{C zSMli4GXH9`3)L*$Q`V~Bm&E%3?p_@B8uf0vPW*f1{ZwU80D!$vg;%#b>%+yuZ zjZ88F9G5kfm|4oI)DG3mgS}BAR2K4sU|u``CJ8@y`uJr^7*&X)d-2}42AP*%m2c5r zRHyQ4L+Q=hAJi*M-0HZm)mB(#8aadJszY2!kb)&RqeGQK0C8?v^?oG5Dm;oayv@gI zJfRaU5(U=R3(w4#1V8EbUW|HYyh?&|X(tAx!dk`z`o*(9y;)7Q%U7dMjkFU?)j}Nr zy}c=>Kvgv1Sb}`$OARfJ+x&4E>Asz>O3Q_`Rh)S5js1#14Bio`^Uxst($Ugo{abAY zJ)R*c#azakDroKYJSCbJUfHUc$KpSYoC<1#jVz9xHcoA~YIX#T_C0fFrlFSV(Q3(wrYyXip2ozJu+D=Oh@MDN3UGfsr5>MlEtm-PZ9 z2mv~;?#vvX@3{gyrv&RnPZ|l(Od%hUJkNGYVO(+*6b-MD#I2R|OA%H9j9phjpr+K>wq4iXiX~G=n_%7guAeZp7W)(F5=d4PGd5Bn ztx!DT1Z+d7*HpA_{%fyirGaY-u>DPJ!u_+N`k>`2*T)PG!pUvZkp5jjti_f0={?8Q zFecwl?t@h}*X)5idFm3+<+=evPh886^5#ChZ5wF&S<7(a3jbbb#LR00a`K&&d;gFY z?_b$PpzU)3i+&TF?tVB@h4MG+a0e73TP6|D3NE7O&*-}P+K)&*!;Jb(G;*NZUhN)N zc8b-_OI?roKsB)zNfRglaX12X44etS?70G@2gN&8zfO8l%_f@g$`%3$e=PC+NwIEl z=~!ce-zC>BBH#7)!k~c^e*@m|HhR0WM))6fbMJ7T@mL7DzO-u}bnG3)f(uO}-04$1 zKooy89m1^|So@^d^x=GG#fWXBDmNfBsgb_C-fML0`C~Ss6A~DZZGnaT8!rE)Dz6wW zOAj&shiuXH&$bp51`A2@H*Kz%L+{nQRO5VtE9fV*)W61S2gMw_#=zfVI?xN8uo@c9 zRd8m!z^cjeAJe^zp)XQ6EU^q)8XfeI9qY`YuNO;5;jhvt%d5{2)RjBvwKcQ60pU`R zUy&Z=I4pCT!rB9zic9gGMSdsUG+S$RHp66ZImfAYP(IQt?4j&ZqT)_r}y60h_G1g&rV^c6^Pc#*3}cs^JfN>RJ%u)44tQx+NU z$vaoY@d|BhcCmZ(rjmc61y#ecm1YEv6k?L2Y;ZK{Fl*4vEr&`}dIY|@!MXb@-1AW> zzu%k}hcN^^t|FMibWVyA5$4GdWwwe5q7Ah(lR9~xWgGBy(@L1HmIoYj0o5R=P7*Jq zImZ;NggXF||FVh$!-?3T2II(5KZs;z56rtIdG5<+6^>N7XOokzYds#2{aXPEH=WXACiFBeT`##w0QZ4Y^bRahHvBfBp~Ltz`>|CHPk!vP{K6?isF zBM``>H)Ln*979-mONg-{XVgG^QtUtk57^p3`=RIKfGg ziTKD6qp#GU5Es`?%T#U@a{rR!(6OlzO7jrU+t3#eI3xRl8cITRf%@FTY3l_1Vr(az8GY2b$IQIPBHQn6p>mzQO<>Tnir*&&TfDDy0Zs>qG8IJC)AmChZflKG65b*G;7u3TH|dL z?KlHxOnq}f2K*#kSj?n5J0!07rH1X)`^h%x=`|!~b*!+tFob~x-(4QktSUmtN^ttI z`FEx%@w2@=VSKA+?G*KuBRkDs5TXGOL4$(bnr;g{&AOKpm*h_)PH zmKgBEmzL%{KMCJ%!^Dmo+CR%?KU>e@;aOilzw)N`^!IeuEHI5 z>YQtGQt^N^5C#xm5a%$l&fFBx;dwMTMlMUs1!zm;8s9eA@S>_w#RU2eSL>;3e!JW~ zv9d0eH}G8ll!+K6*on9}IsS*ae=uiS{yi`TGV2fI`tPzL*AM1S^CJVrK;UBf z@0vI#5f>M8TOk=}4h%4JTD=%B1t=F6TiO6JC;=!72TNK38XP)cM0?M9ivz{)<#)i? z=IMvUB4$#mm}W8`-gBD*6(K_1roLGy`VT z$iWt&0R{7{$y}%r%LFbBLEFSDkww!T%0eWx@I*H>cSd%RA+?3@;XKMe(p%HpXfz0X zY$s-aAh-%7hQtB@P^y%UX$GsfYA%B96f2eyTs&-UF-i>ABh*L_U4BAfLvXY^a8Lwi zE(}CGkQC{!bB_!|*-5GU_?#M4nkWmvrp$2vSELNjDZTk4U8^lsN z%Au<+6fzctZaoW_<3MwWkgm~y*sz$=fyuhqChBB65;?}uJhi?AqA8Mb1{PjSej2J7 zktUKna-Ff5rYW*Tx=cTqFVn=ii_dT;WE-Vs3|ivsU@?@h6p=33@u{2<94S-y@O+v< zqZA2&*drRCWMP75oSrFH78(NlntnGah$si-#)`AoLY+{WfH{9ZIfmLAV!vIx8YU!+>&FGeh@+@5~G`r3~n z?QaE!N+q0z#+&~O#=DT7mQiJ$+Oj|7-sC!f-T)1tlAO}-A+7WkM9y92rR?mE@Q&Kz ze7c-npzbu>`118q`u;Rkwy8RI@?d6Jc{tTJ_55$d=HIUB$IL;qez)U#x{LCc=9emd zH}Q5ms!C67naqPY{q}_$%>W7=RMv83g~5^*A}(J=E_TrnUe<-@gSBy`=tEo7RNFfw zM3Wi7uIHzUW$yP145;}PW{_owHrvhdGyUY9Q`OS7Za}emi0w3uP#`^NXL(zBXx-+3 zDH*35w3#hBQ?%7;dZ@gJ^74~iO4fDW#{y$4k78-_@wPjYF73(4&d2>DZf@#yY-*yB zW7#eJqCA69$CkiQ#p5?mC#hyNqn&GzEf6c<+|EF5VB$hbIb3T8Y`gd$#B+La*8q!Z z-}n8qU}q=Kq5@%$U161Z9mdRK`)W#^K0d*K&&AwS9nD$v`N~oC>f21(laFV>*9zi$ zXRieV=F)rN$a?FgsV`5~6=&Xn0%d;)eZI1Lk=mt_J}lEfvX_>QXpaSOAFAc8T-48e z?xOO&mYhMf#}@vMv;tnWkIVwzMuKQ(I1b=x{(*yrG8XTt`d3_fUml%RHvvlwk1pA) zrYOOzk$az=bwVmNIuk9&+B6t{8&aeLw~F5B6Pji2=8kTk7dzPuKAoqX0Gra)b4~DK zyc|=8Hk!#UL9?ek%-<(VVdF0Fr6AmZ%U?gHI;9>{e?OoGhX#x;Pb&F0`fQM+UEnf~ za$XmqbOUHRBP`c&BhVuPaXD<77eCdb4WKMJtj!2UrJ&4ic*Pg+WD*^J<;5W&G2`w! ze-i$9Nkp=P4~|FME1jFI<+dF%_TEcvKOi7IR>R;z4x(zq!Q?;pQYgB$12=5|;Ja0M z*qa&my~T8IKJcn3|9GTUJ0r8KeH(N?Jhm?HxV19#rniko;8zd8+qn%h_sCax;s968 zXueY83KD%g96NDs2ss+ot=+;u-YhDzNh21)95&-XgodIF5f1ERYI2P607(Ku>A49%|xgcOL~>hi)H3VAFgJdy^SFNwiSF*)%Gl9oUZ z5LOsbvB;v#xUtYv+Jty`?Y+^IJ*4xUt1Bm^t@9%lT9v<~msA5q-tZ0VI-#-4s1A+T zmdi=yR6{kSgn_ms$IEgQVk&^vfrYQ8_{7_T9nSKPbwS`9P{a~9e-|=<%20XGs28UM z0;ghC7uA|`Dsxl(jIJ>$xsujHOu&HGIFPC=g8&(mkh~v1Q~XN*3j*BxQ6VB+vHPR% zsM0%7!6UH9IcTuoO_2$Ka9h@@vkSmc2T1f8`cr=0&!JZVMNxtbj|SzLIWTt|if!L! zW&4nU^5d|pRLiJ+vlJNseuwi-^d417KHN!w+-PFOk9+!wCO}36yeLw_*y><2K;3k} z(VgXuLV4-j>VRv(&LwgmSub~KqTjtTxnnH!{KQ318O4NCl@hrc!(xkJ)g;=eE{lu&h0>dr!6oV^m*5=A)wBsSXOt3DQQpT8)0P z!fQaUao{iPl|FXAMKC3}Y#h>}s{Wpt{>aWu-{o$5w#B6%S@}1ypNsT{W}L}qV3gL2 zE~$oqgip+CU>gJA$HqDX?2%N!Uwn6^cd2TxkTvvMu{P@H4@__BB}vMv7@t^2EEY5i zTnEveFif2(MA<(y&n6$y{J12<+c|Up1Ex^fHT4+$Z1?$T5@0>(7btyXV`Nalx7Ak? zdrxoxW!;~)9+BW8qkGT_&;w%r_RbI-eXg?(1U7<0;~YdlbF&@n=DI`bm-Y?h^9`f5 z=P$#RJc((bKx@&&>~7b}-thXF%LYz^U;^7DeaNPAEsoz(=%{EDarDa=yI~yg;e}OE z9K`rQjiZHth}Riq`ir=v5%2a~C45B7armyVj0Sb-AbV@=$SO29q4oQ2J0kdB*iC;V zGOGsU`Q5=u#TJ5l&VirE;%KGM0#yUseq?WTmMN=4#8&>Eu=P_I^t2ddi=+%RRXMujKzy#)ffES$T^92k>Zn_>uNpDRP311nPnbxPNL; zNxpOs4DJ5VENXBfbpb!p#XnETabU z47Na+jei0|XYQ2<$4H=H9-PQIRr>Ajg#F}z>E*wo6rtXC15F@BD@BDZ1O1QfWpfE`w+qolV`2cBa zn}UR+O1Q*SbO$onWsoJkZFp~3W3oE3xprI-vihnX8wpren)6BzRZi00s7b6g@@fC` zNcN}K^R+kNl$V%q2y$Ducd!2;M%4hbeGhXG@Zd(4M}RYN>I!u#V05b&Q~VU}%M&nK z^_5oo-l0Wgq&MO9SN5Z;j1l3l$kRdI^{xHp!+l7^y2#wLlcUz&rK{7P51^!SR#F|) zwr=br>DZ`L8+t-ZVH+bf`>o5YXyE+CGn!u4XZaR1sdVwZgyhlHXP02e-OZKT{>9r{ z$@vc&ceM2s=WOdRa3+zT(=yC88z&rTY!AShazqZc?;8y_F2F>u<1Hz-_^ z93o!Z7(b{yFfex-Fd{T+8?_*49v=ud(|^Bqyg><7K-gLTLwp&5(}s6IclnwB$9UO@ zxVTyVhdF*Q>;J_90z{1B_I55re0)FPhaq#b{Xg2v&EB@R3+jvx!o{7I!0>YtpU0oA zf3(v7Hy(wm?db`W4j7o_zk9R4fNII40UJZ1w-t$iB~hith=9STO@o2sfwFP3{+A`s z=*raLx54k8YHZ(Jg{Vb%l|f?uy_=w)mkSu|YONZiS0=JZ0Q>q{i9)GZ;EPQH(ZgCZ z7f+^2AQ4nv9!~>wkEiVcNVoPrPVN0ZO0Q(l76Moq^S=MZNHZQqc`32*v)zn%(+ZVo z2zGzIQIvpE*LZ#92Tk`CCcn!`KT!j|3G*_S#Xmk}cJ6t7?BuMWpMKk&9@D-)%8ObZ zAJ(+`bG}owq^1-qmVJAN`3~|wENLGB;&|jwrh!{=K22lc7J-g=?%vks0Fsx61}y|Q zh5q>*m&mv)Ug#~)gMk?p&2`(U9lNw`5HuPm3u`j_JO_BP3=s*w18>ejTZ85EVEm@0tNtrawhcLYXro%IBUBk%aZ7RXwa155O4U$)Lq5$AK~q zwDr}Y;q_1*JzEgvid=9z>uHsWM3%62(g#B>Iu~_Z@aYxql~Z!PaCy!vE3&>cHxsDa zCV#^@AjdeNSeQ!CgkA*(!=JX_&q=$%{c z2^b5?5>|Ixh-%-8(y0+TlrLle^Jr?k@HAH^XB2eCT>R0qDOs^myI3-kw9cEsc*6&U z*2h}m#B0&tK(VN?ALj)8qw!7qPPtxcZq>;#%d5Xevf)Cpv77dq@|Kh>MN=*DnHSnrqxsT=|T^H+XlrA%hqo75~;1k z8g{^>r&;vf*c{SW2!q$+vHD!<<-5lfe7o4C;9J|ZE>;q@JL@c)ou*c;LpMuvbYz=; zQYZixhKBB*SUymn-IO%C+eOIrJ6>EJf~xdf>FKf`zcU>;v#2WxN7-un4*RiZO-Zs^ zwkYgkyJO~`2V4x`G{0`6q*I3cCL%KKYPJod!qksg|1_~UelD?-vu7)3hR={H##l9Qy+i4geQ~pn*hkH{lrUS`v8uS@F zqNVB1I+G6>t2!aVS)U7^ilt&Q7mRR6h#js>nXRfQ2Vb?g9`U?u5%hU_TglUjs+wnh zV{kdP(w7*hX5MXko(L)C7mnWdu~hq7%ss)DZ$<)25a|n+2m@B}-++%CaKLfQ`>(V) zXNe}Xyp}-#xZIG>_7@h$?48mOh!6=)Gx`fTN58{9bN6>Y-?}#flhbf>i}Z#V*syV2 z$S{S>Mu#OqzReWAOw!=v(K&@^QW=mT2Ary(w2!`TAOsdGSxO?~91<$nHY$Q9Vx0U& z={TH^Gk{H6!cTk8-uSj)e;gRaCD>mP6=!q(#6%I$-*U=8gO#uRV(#k`Iqc0ROTr;5 zDpa3zV+;wY%9{cw?57y-0GFAm@dfo#yGrB+_hqES2g_X za0hwo>FhbEVT5Dba;xTR;Aq&3fqoXhu-wnXp5!%qKZ^&SEr>@}6I^aPwxCTv0t1KA7#ny8tnRHZ08j+HAv^F zhy2_lQ3MrPb=-nSNoL<_fnkt;zF&a&(InqAgU+gx3`GQpcEO`EL9c}0;($DQvnAwd z1AJ4*cAz}({cfOvi2Yzs{izg3yoE2~@3@xUH{4S@K1nt@d_woQ zhjNrwR4S_=2h3v24Qt z9z5`T(L4HH*|Dy!cusI7?N14tEK2OUlLSn0cdaTpU^^ z7Tq#(vR-WTWn&`}ebQj^%67k8v{h5<+6hAY{t_6Zx;{hZDCtK$hgYO4oK6Mml4&)n zzGI}yl4;^zOMuMLunTrsh&)n80$vtF5>Q5hn`Tk34n36KrEbt?LeMX7Oa zu-y(yfLf1C3<4gfAdz+pSL@2EEs3uVqu$?c}69eSXa7IgNs;Nj%9Yj5TZ(uumhsy;(=Uo4|IVM+7S zf{w6^Zh%qNO`w%sHr*?|yB-3sGa8pv;h6nx5~33YUA?CYJun!zTsB4tP}k#rYwD*7 zF&K+m-kpzI2DoLRFv9kzOXg_~_#LQ?0pjN?GJ-Z<=&s|y3bG5q;a3=Q(nm~AnypeC z$kFi(1sB%HNZWdECNrE5OL(nXPRomoV!c}WpDgwNybJn;vJ)x$c4hV{zpRjzieO*) zmF1!uZA0gc_5V&_SyF#x#6TmIKWpGs7eE zw&$LZG8&cH=f8?>Ofp*>qzK|yI9-?UuUiRBI+Czrp$?M<+M?-m_|fvp%J833I6G=h zNtr3CJs%ya(K;z77pA~!{jz1_hrd*7iqw(?R~cEzt`+v(Q6-`_Q$p9}1(}w6N+~V{ zaVy-E12hF%Z{XNSyD956yC&pAkQ33e{bpx;lS%{FsN8mVdp@+br?zDxO$pj!1 zuu*bz=s*|4TJurf^>GtWXx*5Elw$V?@?a}XIMJ41O zbzU7H(0Zvx+9@a{SU55Ntdhhu%_qpVvT_) z=c_C9&P^`Ol%_vpEf<%}FS6LZudd5Pk#p4!@deDRam&r)@-KW|_o&_WetHzoiNGMP zHQh5~&qQ1--Ek3LqvLXbRv6=ArAP+w7kLdrjOt!gn^{@?G>`dIcv=H3--^`3Xj%X! zSjOpESLJo9a>mS>;$#LVmvTUlg~te1jitfBKTS8s7$Yn}rxp^48;b2x5M2E)K%ey` zigMG!jB(?;(7Xyi1BN+HKICJVGpiKtkou%hmCIN5<>UmP8%?qwy^ zz-!F}S&P>r_@kgDr0$trBu^7L0G=6PJ`DFU%hpyLE(#t=v;Y}oihPtxPJZbq9pQK{ zR`Zvozpp8~XqIF7J>3?rIvm?)HO-VT;xF4UT;x8HQfJk*9Vxm9C@8&#$z^^e%R#?p zDg<(h`%OEn*brS3ktD}ws(#|z!6tYe=d}s*AP6A9g0-3MZWMm|{k!{M1blZu@lhSO z-3k_m9|Sh7DoOGp1H8V4H{APpfzg#cPPz8k759Buf&x_Zh0vw8l&N@`y`uFK!w~IQ z;|s@)Vj2^7skq_YP=)1}gyi=GzLi3QxSq3leM5RQoWLK2WjjHA~7M7qsP;4Pur%A z9yv^`Z86fIB=&i@0D>uvYm|o=AAi}Oka_za zpwrKBIctvZJ0ENYz5dPZtHpCnbJ0jD3`)(In!3DHCOcPk`60ZHj2x_6K^(|W&RzTo zqr{{EW4>UYMPPuN*V+0yfVS|``HIc^yHDA)QoCFx#~`6e3NYrNG=~^Vqx?%s@Fjzc zA=41)bGCAPXd^7Z!amXRH{kvaSs&k;b>mAQsWeTF{Kfx?{^VsW|8H_ zPA^Aaj+BWR6AQ?NV&?Ov{|6E@4#qR<`Q3s~!>;goldpJds1|+oA*N zvUs(aQc6jPv%2=KO^wq7hlfy9OIKrZGb!e@K%dKfd(w;4scUydtRmCdr*n9;!BKmm_e`oWqB!AklWUKMg9^WA`P@U@>BpM^IVN}oY7k5!=Z4u zaO=x_ev6Koqh>7o@}AoRQ|Wb}k22mC}1RN~^1I_!@GJ z=Y4Cc;|=XhXYy)#=h>Ov{K3L zgSAKHMOWLUJt80j)%G)ZInFu|b$}KI>Ez5V3o5-4>Ke9`Ukh?eX7$_sl&9l;I76rm zKwpwlHN&UFkvXq@*&%PXVL27fuylQ4LNVo4D2N966MTr8$(R?-I`Z~h*#KV&2t@^HR`09d=feT)gN zf&09WJQBDT;IWECAEo@kyE>MVp=!3@@2f}g7-)<73;hqDit^&EqPvwnq>M{p^OS|8 zo4)p4T|LJS5@!GQvA6yHRzG`Fr=hvssJ0Wm?`x{;cdy^S$IG%YHfKN`5j(4RoHuyZ zv#|$2i}+smvhlVX^G!K76o2&V_k+U5m}}EvGmh!AdQq|Qc%vWTZ5ghjG?VR&xcV+- zXe&8RuGaa|-Z9hJC=c*~V}%+O7s{BL4ydg5?+_Av7Ze$1PvufPkK&On$4#C0ZhUKQ zR?j?D^Gb`Xvrr<0WW4Dp?%T`tP9wk|a$>JM4 zF*83SHCK~vSO|AoS-YaAT$F~RqcB`cB;$&%cQj10px*NG5NoT1ykA9TWuf4JKoF<1HlN8x|K@3E-_ryTD6>z2FvK%|2}U4Z zN}eZ^NhVqjNMq9j71fuVBC5#uL^|n)ZQ<`FMd-r;FyFbWUIYZ@t+X>9`{ewJTEPXH zvD%>btioq1y+F?zB@*}f_+N4Px-IFqi#888_rX6dhKsIH5jaOzQ{xfz66Q1jHYcoH zY+p+;5*1Wda^m_G$?@A#_Y!`f=Pz!Qa%UQe$?mJXgcpS&MU{H|xoSoW($D6Sp5l>7 z#C_B|pL~}Q$Yyqi0t|;Kx=H%u>8-fDzJIUB4|Cr+w1FZGZl!r|VPn+H^w?(sn&v); zE(5?#`D2GkZEvgD#su4(Hgdp#O*G1zjZ6>&ZTMlkJix!XvO2*z;wq71Nd4^&ZdIky zueR*0)I{p`%k5@3I~yW5m^f==Yz?z*-B?|SYc>L`msV}CH73=?K?C2%oWZ=ZbX?zv zbD~W=CXXRJX=J_at)By3D&zq^-{ZOZ97)z`10sGRk)r^VsD>Tm$5lJy#Qd8XPA zz@?dvFk2)Lq~SGuGmOKWl22&DM#hYN|%yHR;R@r3QHndTj+2yj>_NJet*{P=Hfee?lk%`NH zqyO19lDQC?Dks%IT4M%uCUJ?Lw)1_hHOQp0Z+fTrGjw>fN03G9(i_?(ASJw}Rwe6BfUdOUD4>az<;E${_kG5y$gsjpEp90^${vii zpzn+-G{T`L7`8uK<%USyX9#@^=R}Kely3tg7d_^USME+24TJ#h$Sb=!5Nc#&6G9{p zS&PI2<}HK@w1JtpNybmguuGt%o}dKHJGg?F2#}{Sd{5HG>0z#&gw5wmkx>>H6#=cG zUL#hes5W;#KNfl%evwZ`@Qs+Iq7x03WFfM$3BEw-I!F%Eny|pjA{YEl$tByDAMNV6 zoF)7JVe1^Cb79(M9c#z7ZQHiZ9otTJ^2D}n+qP}nww?2?v;N^X=t&Q|d(w4RUDXio zcVzLe5zxn8yHxmWa*vH}kJ&ROu*3!0F#C1Zg=K%Qj4h@T%6DAMC;CR^RkLLd&t<+- ztG2mT&ZU~tCdJbsRT;_`K=mb0tqvu+n3`Nu;f1TNsFtN^8(7anq=wD%r+lF+;lb(< z)YAJ}tzaICI{v)#sq3Vu0$gVZCIO2TGwGDV7yw?L=G2kf9)@Pp7YtgD0#g`e5~d*D zAJ&jL+r%-dWlC|ohKGi5C3Q(t{PO6-lo^K@YhHSJA{<+oEt`LWvkp2$q!!8 z-I~{(R{8Lz>e_rJR;-}a(TdQGn2oaA1e>iZ^Yxn-@uV;6%CnaV9@4NC{+-@)c7*Xr z98k6QAFLgw6U|vW3OS)lTJ-ZKp-r6P3Xt z(vjR>Xw~dQT2fi5r4U`5`*lm#QPY<#@xI)XJp7*q>J;DN-V|I4y*PY{;>4H(wdVq( zVgBZ@6q5wS;Qdoa`X8oNqIM=k9uhdBAV6sRVnk91Osvheceo--tZ+~Uf9(ZBqqkd3 z2p*n<@zCK_1#W!$cZ5?Aw59g?qp4C%U;c(&5ra7gI+Ut)KdFWU)RHa^$oJfkz?cE- zzw&84&Q@VWQs=F0B0Z4f1+MkkESc0ee7ti(o3TJVRQ{^J69_{qXen`gEG@asWq>+P z)=*^jpp*AE#ZZ?wq-?Q6ay?SsZ?VeL2m(woIYbpYum!~&V$uK;m}r&q0?wxY-aI>r zj*A8fFW-f}XMfC%8dSx$p(LRqPR1P#6 z({w`1y-V$?4=m{^Zaf~GTj^`~7$6C&0SDDHdLIorl<5Gjg-!JGViu zA{Z9bOjRS0m)it+|DLI4_%mn=>jJMzvQw1zaKrSL-}qS|5k@y zPM``ji+Pfu2uSD&-d*!pUvrO3j;w#uiY^S?@lcK){{g2PZ@4_{n4~wA^_m4}PTDqX zyd3YQQJy^!K$4+4t`3uSNLtuO&?}$Tqv_4gg(J`#v!aRnG(+}nI{Sr=R_JWg3tM21 zFlF7u?ickJ0kk9ud0F{P#+qG7mrh8QgL=z;^XozEKGH`vVxX($O*f_V)Ywo1!Z5X& zP8FN*!u2DzY55-xSE@21I9~E@1Jm%ORG$)?rABP%wgh1|pGj(^HU{b5lzQj))N1w5 zUe@;@MCrnmd{+vO{~m?rHmQsM=_tb&adQrnv6GtR0SX<7pXx$@TfeJ#WQjcnqf~J! zoD<79BUt#c-;f6O5~|czCoqh#A1NR$LlGS+>GyWJ3@H>Ki0}{&*~(Uf4+w=JyShnG z3Cz+`RoSbi&6(+@Gc5gR2?=k0Y$H*I1f$;_C%RZ^U}L%Zawfw65aS1~`16?GP+6KG z9=SHw0RBis12-?=2>+45+v?oP((69S@9SRnq-3-!PSh+{Q*d89gpSE#c^><9nT$YM!=&5N>Ec`e2` zl130QVocj6jaNVel3mXX^xPMM#pN|-{pce>B4Ek%%4;`jbv-_K(AWf{`k9#lp z53qx-yQ@T~_hsLE$iIvnZ55oy{o^WGl|`d@!k4ww=YT|!2Frbp4=xHyEMyZ#kE*C? z)_iVuy-UMFCSBn%`cJRs`vaLxp`J}ZVvq--Ou*BE`m!31zfeb zR|qrR`1x)MH$nNj4AeH|2pc;fsrt?F0RL@@Xx;AAdRM3_5xBJ&^{dbz1r1T1;?2xihFhF*1*_4=mh z%D!EzeG%gibiNWjIVt;&@@BK|bBk9xJ0Ig&6~vrfnU~V#3cYNT)78#4(%RqJCn@(e zMfExT0d1LL(SWTo+pps12P{6k$B`%Pa zh-*BgbJ)h4c#-l15yUL9)Sd5%^qOWm8Qk_$B@j2kWT*5&b?HC% z8qoIwDY8Etck4CqdS@XQI#0)~nWMRJHR5SNOR08N(|xU_qw>9VG(-TV05@h&!GCdg zxvnJ7fLE+)&u++xZv7-pZGdRot^tJ1sJJ6>w72^$XR+b^AE%2T6oaUwRs)gl zhm-~9^687sUN@ykpkNE(8-V*FbtFwtc&hM>xnn5S(fNZf7wOK>F?{HGG@S*ME*o zsOrOsZ}@8yzI;7U2Y>_Kn;j_Ou@orc-%K?ZOPc%o4CwvPX&YEUeK);{c;LK0WV<0Q zNB=@`E{roW94a02V_{ET%lnz`T8u~AAp-pj)CB(f+^%ww=jS?BbP9qZ;Q8|XhK9AT z(b}fn*QHX=a8pPUoIUA}*jo=ZiPg>1xswIAeXkwv+TQ)Hh0!SeS__Y?Gmf%V+X)No z4~}yDf-W2^JpT{vgysLchQL^vn3?}C7K$qso6U94-&+tnp3mpz8Jd&g;b}=46Nlq~ z2?u_N6XbhQP60;VRN||;pFH6GFT{Y>=jYn}Vp>#cvhNZn?d)-f^MF|d32ibV}beVI!7dPD!ZfC5rJ%fk}8 z_4Tx0?wsBI`R)Dua^?JW^@BOubvVUhOC{8fH_%HIX zWeLphhP9hK>xQCjU>@g0*knd2|5n(AI&q#}QBn$xP?Z;eraVfKE2`HCa7@}Y75sR7 z=9;H{^tHbht>1=Qnmt!%>r%93m3UJ{oWJy{Q84KF{(7FQ{pC`n0hihWbr{?25*R2Z zgfS;K0epSk+8glyzCPxQQ`aV(D2&Oo8IVoS%{Z4K+~y{Gziz%tkV}Iz6mj6*WrQb4 zQ3ZO(DaHv&ax8j=NoXMf3fA|OPR(G1nL|^Adh*geeAsu;gNJuRn9ZB5Gjf)X`Bgh= zrg+l4)y`|orqfNHFE7@X^e}A54;f8%(*W!;3$|K%kd#s(9%^Wa)OQYJDP6hnG5yA;Skp)1ycLC7=AX5Od?HtDHY` z5jS&Zb~HO&&QqAg91sTID<8)Y_N_!l=w^b{l)Fu<1k_=hxNJNjEdp z+d&yp922NWXQYKms_59Mse&kFH+s1A_62VtI;T8>^(?KRLE~owqfIBEHT5mNok&Yj zeH{~07!j>DF)en0VUE?z=}GMMn<0moPWV7sVFkVYCBoacH;I%nX~~z!`t$AUwP_;r zZj6e|#PA`J+B_mpa50XyGyg6m@@pwz1zbgK=#;{byV+WU-Yl$VLS3gH)T^zMO4NC& zSwFi`3+2By+3E9Tud{pKow+gf#UA~jcZqnPz$l`3jQ6$xC=0g2Xi3;0(4-&wpF@3E$x~pP*LZb)xrlzSS=s zi4XM$iX2;w-cvZ^dj}3<#;Z1i_)y28dXEX~&DlEIDAk~+m_5{4ig=ZExQ1@k5mv<>F@BaK$(Iwc1YhoCt+1$&f$1{=IryXfl}C1 zA^c7G>TE_|VYhyd5+GeLo_y}+9B%M0{I3swcf@zfe{PT{1u`!x5~)S@2fOvaY+M$( znm@lyc_UQ7N&>{nY$!Dy@psKr=~CJd5inlz67x z*sGTt1%cn!-2aADFRcutIRYhfn~uUWx&Ut5xv!>GCxtmG>t~dPKWY?oHt=keOX0t* z(rvg*vSBk5@_(51^+H{u&&q$89_i(>C$N(19b&!t@+ z)B%9AwMc>w<9xZw3~>I-gxY2M%!YEWgAXi?Hg()fiSk|iRKeJ`Im#BHQr$Y55qdo3 z?)C^QBa^2+j&4DX8Bg`BYR0rd4oul&yFm)8DQ4@Dw|LCLoTq&|Y)1FmA8r|>p$Q{p zvkB?k>8z~EVB1ts{UtQ#e&xZp?wvn5PznIWZzgq2huoZw7K_4xzw-!(;9b!{fcVMH zBew)m6`dS0gZ}^q>JMi`a{Rs)70ARP$fnhq4;F(fc)@X_ZnI>a=9uZ`O5*gA{uv7D z$f{&IS03_eJm?VNCoyjMmTKRZlrwudpYAIa{X{lV%an}E)y51Ha|-FG*tjcuwx|FX zX&{Lp?NG=M3^)aqf#kd+UJ!=FH2%xDHS+LaRXNheRwfpvj{k}MrO6`m z%KPyolnS=O?@0(r<>S`e$?gO2%NxMgFi1R)IIg>R|0#C)YY}2`f|@RvJ|*59<2q5^ zz36Ayl0xzu34M5@(BhLt6oSAv2EKsr)l>UkdJYM8=ni23k35ozT?aWAc3rDsKGo`Nc;15%6uIl3aS z2B&hC4RU_b4druUn(M*s$L%Vr`5}ky&*Lh(Vr69f?qfxa5A*R7IY9#X4;Ly87_Y$7 zG;3kiG<^lR6mpq z4Z4K3dh_B2GY%Uev(I|>shucv?6NMo^^z~3d3p zbw}=xQ3Y#fy+bk7_(yy^*sd_wokP6P`$XQ5IGMKL9qnk@ZXc?~7!ttT5EVpUE_@w@X}9|hI#-l#|*soF=|5EcM&f!J{p(qd_`|q z+G!i26`o-zd#M6CL;_$K+$T!cbe;@Xs99a7*S^oEOMT?1nFY+TvFE&qX=@p8w>$9A z6EN|sD7>LQGC|husSIqSs!Qe7gc4scx>kALrVPSN4r6%&fg)RtIAd9&>#etNM3OiZcU|iyB?5pBr`(e&XC*yv#a$)? z1?Bosw(9^f!63it;90CjbRCsyvVa=0lD*EWvu#3_{(vk&ArHHbJ93=azs`xI0s|dS z_+%u*8_2uZ9*pMBTECfV<=K+2jmxZD|MOI zb{Ee`>X_ZjdI3CrJnf?zx#$;z39Zi`o~_Cw%cFK08j3gG)-#P1*Kgs_2Ym{zqQsI2 zB}?tA@>&?*R#59htnXVP44>2&j|nNj22SI(KyR{563P`U+RJw^!tw3A6aw`{4?tID z?#N#C>=bw;ZCWGLibPlpFp?qUL0((H7RmT+3G3*}r~$moWb`N}b-Sr_aY+X4bJXnn6`jiIs ztsOv#7O7xzjEyFrEmH>>OEQMKwf>Df^T8HL%Idn-cNPVth*qIl`9OPW^WIXg4eF%r z4jPyHavwML#*zY#`KjivGdOT3s0>`jE@6#15rU5aTMc?G5<@p^5YEq=VU-I*D1@}O z;kTj^Uj*kDmZZxvi)lH2d}!OYiKFPp36G})o=>G*2`Y8}=XAqxOhz^zIqR4dG$wrdxKqT5hq`pm3* z3s_&1@8iIO<8h$indoQ>kdEF>%xHKZoY1`AwA^n#UWbF0$?{q!H?epPNmP8)3`?Z= znE5CL_f;Wvsq@KsKFn0P43{P8vjN1Y1X@?>vp3R)g2UMdrFiW`i)KY1Rlf#yLvv$T zJ~#mJolaiyVU~o++nxEdR9jbVrQcHnhNs{kA-~-$UaF7>1LtY$|2jndOcK3dvNJYB*y0+smg; zo(XM-BF|;HWpmh4LFlEB9#zat3pS{uQB}UqhE1HJZnQAA9Rt8Q{*|zu3rHRes8kAF zI$}mb3COLu-VbCp4C8iD95=eN|z7)@URZ%S9p<*XDJ zt zuznJsi!jx_1izUOy-R3;L@>7_s&77|_+RhSUwLDSgLv0Mser+MO4Qu2+ggB3iE z8-@%TC7Iw(`wg3H$@W)%+)zoh^ElSDzyeK?wltxNx~W=GAMN_TqiH^F>-WNHe}~PF z#T0E&-IWIgBb*Swq?BrE_U^+!V+wSGH)tl*Zuxp?EZPjg%no%_S=hB%S0tdD5QIj{OB`~sdQM60?^n?b5gA%RDvCHto@&O?f7(Jf?_>;Vd-Usj1a}7lUW(`il6ZmN zOielX%T{YM!XIOsDMKLRkD?|wZY!o0r`?VwwKP9aDpA_&%s0HkO+V?K+ZU-a}MKq36g=vvii~ji{ZIdR^=`t z=C}0KIEz_hJ@AFpoWWcBgFKjQ9%1Kw@(Uf+B-JtZ0Ol2uWuaSR?00cj!1J@z!1wo+ z;v&56s$Ikv%XPNbEaF(-aGS;sy87n%*@c+Z_s={5c|-0@7)n? zvLOuezUSV|T0gIE2(%;DKyRw|MIW$3Y1f5dsR=}+T`EA}@x*`r=j8{!1NJbP9hiXurPZNz!lIdFe7eDUFc= z&aQ`nU(FUNTIa1n4@T=_zOODm*z)PRq>5GcOk;2fv7Pzme5mJNQ-JUi!Vid3{m*LW z8+gVK_UTtx*~pzsO8Ma%;@19OLNt$oZySPHsJp!DFk_^+SiiJ!`G&jky1tRh_&)<0 zXkWHJV{HD+Z*MYrMh+?U^n1dz?G6s2*x9wRVc_H9VIT#{u9 zFh*g5FWd7=UdTN3`$MJV}HjfORyp3db=?^c zd~=^rG{@CqtdqW>PNdY^SYbG?wLFu($&}nw?<;8*`eiNGMcSysiPrh-Y_ROHxJP-U zRR26CZP>VD>72gZ1wjskqWgVY!8tup$OUPhAK>Tce1;zk z^OqnW1o6fTTU}F4c{`E(z;EVwi2@?UDZ0-qtk3nGH7siSCIHZ4idZn)4@N>aSYi>F z1W_2ON;k@c?FrgBI1t~v_X(ETaEs;Tw=XM7PSpcpu+nOYS%bFKDLAiVzg*4;eCj#uoyJS>Ly!vg|Ou)Mp83nhcoF5!Y-l{(U zlp@=3YoO=-?9?-aSq4%q&5j$lY}ZOH?P-E9(|h^qIl}KkC0=D}nO1~&9`4ykU|THp zDg@$WnN^A-f92M4(}%;;__z<>ar}dvkAE< zB~D2=!|*BGHqpf;XzN=Ap2aPav-bN?_{9Z>@C`dX(+sKL8Fi>jz`McucIqn`Yz20V z)OqG;#ujLFIW^6-X&Q%+ir4T9Rv%VN>=c?{K&F@bD6f}~$U2t;?!ezD(?L7lZNjYw zxV?LLUkb3juVtZ=Mq>4J;!P^QSn4oW`W!9n2F9jV=tUtq4Li?GD?+3tk)z1Bw;OqD2)5NXGO=Zj;+uE)0 ztPwHoG3G;)Z1gBbrt=)6MTF`VuTyw zeA);ZsajsI_1dNcL{vl4Le5XxZTssM%tXU)W z3u~1aL;dSRm3N$DaBOm1oi`~2$IshD4$N-uCEZPnV!h;TW2v)~*-}2{Bb0pVL;fs{ zfW;?_W?(K{%$~I$y|$ShM-TZS9Y@rn%M5tNE<6}mDs5L^aKE_*r^8#N3&aS{dTKLf z|5vcL!8^*hXLXsijeE0DLiu;)B86}=zVAz z!^~Vkdp>1GlYG&wI8bG=zn?F`wapwrs(H=D5hG61-u>TEpJ}t8wIM|lI$pRBM__$p zDrhE8R-IW6Ig2Uid%-&H7cZ90b^)H2FFH-+{tSw#Ud>615*yiW#!^-6jY^0!09OfF z(l&0)x7k~WuT7q@;U`=$Gb0Vy`YO}wLvhs9oPmVyM!=BcYe=bMf2Mn)e|b8{<3t#y zi(0WrnUBFbs#Use)jIej~U0HGW42bv5!<-f>IQ2D4WDNe!k%fy5Gz zg7?HW_|-1VeylteBcxjYo2>4cFTaX#sRRO*VRwa`d@s z@?T)GXdOnAFK1ndx2By{%a7bz`OSeryOgk9bX}7-jlrFgEW&jUI9l#Y852K-VjF3D zL=HUo8XG$KB!kf{oCceo*B<*lg{k*|9t^3S(_CVBq~6&lSv=ihF@68KuZC&d7cvRu z71oP7v@&3>|G(;SFW!o5V^3`ZXBIP!Pg^58_*~jk3GzTFGQiDr{!0~Yn|5kJ>7~V; z;bj@q=V6yoxpoI-1(NbHHZkN{y!)42K>1*Ml3f_MbY-(OaL*+$lD}ti-Lmk*S%!~poxdU_W2%^>t{d6yVGf){C83HT~*_*yW9!Z z^3U0SPJzccpVykxQJ)m7b*4-SUqRu1duRwea?caPUm*}jrg7zEZu~JLASHn?Vqzgk z(w9FoT+K`UHzpqk_8P`cr^8HfY9WjSA6_XqT>Yzq<)1&>)#{CQTd0>AYmPog)r* zt%AfmUb@oK6b0wddg8MkQV`%pk|l}Egp|ljD*+7qKU9GVaH%abp*1{t+it5|I_UHvjQRC#UB78p>e8N8kweKB&~d!Zp*Ia})2E0o2UjX@t`?vAHdE_uI_WUI_v@XIvK}{s zkk;^mDcu^SktRYftd`h{l>xTP^&J=S4qH@B!{&)R95@!9@TZo7`X36X8;pn&mP^~2 z7r+&*Q^jzR+QeoN*I|1ZoJ6WBOvGoov9){ubi#g_r54;uqgu8?^w-WTtrW9?sA1zL zXE3zKpqJUyRRUTxZOzHLJj*`VajLPc{{z>D<}+`VPf%Y^509D_?3t+PX;D+v#eJ^7g2Z~SB7jbU>Kit6@Or6))5_*a^?SjTTI7lMqQJA} zS$cv4eIMD5iD}NV{whXiqGl+_xOsa*YTVhQViarN%Z99}LGsU~CDj-Ald%hRj!Uqs z;cj1)NU;6`|2zUX8NE7$&KUCY`e0jGrKR`PIILsziBjhy?9WZh*`O5}J~oD*E+D+c zL!#r>BQV4TO?n}(ncswvf^A-DSldCI5aT5rwZ;YJB$60njrl|QOmBorLJmJHsFxe2 znUVsw;ORtHgBzpu>UWIML(U$OW!b{8?$NT*J5k?1y)pnT1X!}L4(q>Jq4zjr93wmG zCWLoGEP}l-mGdgQyiUSz$Z(D zS2Z~p^1ytD{*q&D+0u~xReof+kPA#+^`r@emXKyOuRzKHJ(;W6LQYjD|p z`720-SdLBLK>?IT(Un z)WZc86E6!}`QKy^_q+udTZdYQpSX{W+4O~S$93b>QgxEKXWQ1uQ~5CYW4+3`fpR6i zFRpKDiu+?aTc|(^f?1z9bwTHBWOcK5dttG&ImUlXMyx8ByZ(xVE}u8EANE~qKj)XG ztp3JZMyhwca_P?)-bhl=bO0cad#H%gAnUT}Qx{-y@5ZZ7M(NI)K_8oQGf?P79-#@I0bo zHTC>tr#(D2-F19{Sc^B#grr>ez)o|)RAUF+oK!5UYFdac`i*$n4DhPz$Ct*tCMvWy zYzT&bKB%lB)s;((6_dgi$}d1p1=$=&)wJ~r%fvwXyMH7bN_5;`u804X;<^;7Xr?^e zL$dL=b=w;U1N|QtK6OLpzl%*CH21%URboglKe>$YdcStwPx)=tG`AJO(BeXDV#E(8 ztGiRa7h01tH~hM(Zh*`z@9X=h;I*E;nItEDj8`@Ckb-`KWmG}742mDZGHQ7&;m~AU z?yO49oEXlLx8_x+GG6gF{#h`Dobh3=rxxVw8qCWdJ2~lc;2uiZC6U^+d6U%HXqKc{ znc~?K+9fCgs`mVo?}9icziftA%T2XfsKPz$FUhUO7#7ZyQ9!2)Sac1Q^{Q~t!O86f zIs}ph_t6_k*1SzztFvhGV8p384Y971>C2Tzh$ED)Xg(D(vj)h)fixmnnc8G2MMD|l zy_5qN0{Lz3zDtp$e)z=rV6`)!F}bs~Qqsk<5xy?^hHN{RZy=|vh1X>&i!<>4e{{T1 zk4$s!m4JbKY(TzaL-tnT@XHB7Q+D{ip0((SWZR|3OA=pkq$CViCs#ErDd-Sa;lvnh zHP(w4Tp15PH{~R`(h%|4-qRIEpv)%CPCut!-AR70Gl;cA_Z|t27$blRgZ1 zY7GoH#&9s3GMJigbZ8}m=RrGjn5%Rr#G?b;e#ikbB!DBXfS&4MAtA{t(MlAadX|9h zqdy_?60uF9cLuum@U5{eKZ0XNK+Zi9JPgI+UrX6tILG9J21Bf^BVmp){dWpkZ{=jO zgHoOlNp`8BCs(BE)x%2SG>)daaGD*q6Wq4mBvDzV8msk}S_YebhR(>WhFpe&Qi}3! z#C9jWp1IlzMs-QqU_w8Y@l$IA?9@XE)1ZU`wc$v8kN&ga*FT>EE`9eE9I9+H(c#KW z)OzSet~m9(Ar8gZOSCO?={H^*OB1@u9xzqB|Hj~pzaXa#;UE7)cT4pfgrEjtV@$n! z0zm^5^R~y3@;Lqc6Z;iBec<;K2UV#p0jr`o^Neh6io>lYlIg7_4Md89Vy>(-kIpHd zI>LJudwkioKe^uZO}qcSo+SWyuDz+pX6VA$1AbN!ynPw%U#f=&-#${Dd9wt1zaFpc z2}X*%ez1%m-W429cegPCpZ^fpV`}GHN}m8sy`4Bu_ot2DhhNtl_B*2jd16hczdoWK z7@)kR5yl-(zLwT+o zBGT5KS)*&Z%tHnXx8(?h@xC>gcW+g85}@x39xAnPp}m*CuiSA`I$eMFXbmo@4OI|L z`$aZ>+-ZF7SCP2XL#YlTzj7;4ib6R0FK zi{Ut1-+xGB%(zRp&iWkeb|VJR5qR;~uJbP*=ob*KZBUK53A(&+9z!^45VsSCK*EZz zM=`hXfnE>wo2frA|Ldz=uOu(H%ZFxkQGyKuIr4llwT(}1h=;%?nFL3MA%KOme^aN# zx;r|NZ@{9>7T1hdi1Nv#4&@ZJ3cd?!-!d+c6ajd2PJGgl%JB);LrDRScA%gT9|*m= z_aOK?fccheK5_*KY{br1a~JgRXKhN;pDhHAbj{JsUXCrU%AQf^xwIXIFuk#PJD-=a zkG6zXkwV_`>V4st!*>*SyNrBxuYHhp1fT=|e*B9qiS^x#>H*fPcn_n$J|aF~lG|b& zm5AZukBRPM0Fm5o6&(gZJ0khNMx{RO%AI^TNFkws=c$=VgKGru(Lm?$RA-i-GM4Hx z0R?al%Q34gpmo4+siojd33o86pab(+m=(SL1Q8eIZrBF&glj4PPNPSi{xUgJ%3p(> zI1f7qhZCtdM7h_a5b)V0Qg$zPfu+?|O0xRA!qD52{g6WsxZ(pgP<#4=$W+Mj!jhzQ z;mh+N*cZJ_46pCV_VfLx#dIEYQ?qajWhSV#eMQFltMt#yYY0VdSkh-PJtJ}OUg68u z3C6|Y)M}=n!jp*$E5lz^ghZSDNR@8qr{oz+GgvcA%%N{4o`QUbG##3Xre}U2$|EO7 zXNZ(lL&2|gHopLgmUE1oaIU;&CZ$7`VP1u<;Sb5G^G(vr<#ogtLE6bq%jashc93-@ zv8-s=LD9+=ty_KTvF#Dr3xTX@e-6XtGsPHZ1dT93uieeTZbdRp`an){BMiKc>A?aP z)nVkKMu_<518^HPZ&cO={X%$V#^Gq_i3jwU_447lSOo$8VzbvaQvqMaT6MuTWfJV7 z5eC*TS**27B}dosjU*pGY|q0X{Y67Aw~<3qL8WeDq$F^R>%Y=J2m3D~x7CvY8fW@_ zbdGSTBS`X%6-)F(?ziNa;V4{#&A~eubEA~Cu|JQa!v~y{;SMb&gMg67p`@ta~puipQI3T4)we_*4@# z7}cx(*`equ{USL8Gi>?!V6k%!gs_K8L{KYK>|a)9UL95`J_|9)ix8dq*p)60Qvcw` z2Id!Dafe0KgNYRvhCAPE^SZgzUcEW`YEuB>1boIiesc|d7=~sbyHluw^I&89&&FKF z-Mn=q+zwQ9Od%_$0GGD}9px@k&5v=1-CvrmV((!hwAsyURoGA|A#d64Y1vm7+BYDB zu}w2@6{dvpJLg*p5g%xxO`OlW-de3jAt|e5EC$?`3?HyM=}fi^qejX4)39Y*3=M$3 zYx`>tkG&YCqx9~xz)}8xu2LjJ*2v5LYBk|e{HD{b<&MAk^ODoZ)LO|k=8aG-I zu!YJqF9;aps4cZEUUC$aoo>|NHZ z&64mFe?|vI5HOaD}#us3d6b(!Q3r^iJ)s&z)??oabw6 z4tU_Wu)02B8cO%u#!X_ptPP-?B(i_MN?wG4wkqv~BhUdfK$=eIRdg%|I)Sk7PBh4t z5XXvB*AN+96K3_XI8)Ce+|*1xPtaToOu-2T>{0dpvsyo0)ELd@H7i-YXCfGEBFtvW zHQIQ#_a&b_1H>(@W;Jr`!KVC67sG4bw=dhPT7FXq7p3tFv5k#jCIrwLx9FHr2DK&7 zVDXhI;n1ndWIdBgbiOmMJBmyQY>8pJch4r>LP-hK{Rz(#!l3){{S!(%y(j_6opSUw20teFS;?jxTkJkFQ?$&v%3iHcd33@^w9$@ z7}6#6tGAMuM_(Gd_jSW#+RZM|1Hh#vw7=g9x|`E~Up3D16^LcZCX9 zn7i9n5vB-(bOw{|wf>^|kn;2qI=57=eLj{P&IJu#+(6UnzK zUFmNRaYDo347r@Gt-kIli{~5xt{X@u?o5A77RbzVK;-|KrO3e**e}D130@7n_GZ-s z*sN_@GXQ!PHDyuF{Spi|*ai#n72k51;?MFaSU#`NXODRumJ4&t*!X-GW!X}k{^xOw z3K0YZMLEntuWpw@9^+*W>$uOXtIHpQv*zVH{1>ud@gwJHnPOff(M$5?H8f0FJd3jJ zSEW@d%tjZYxjs2(ra3w531zeUW3);?#F+?b;Q*5wwx>6^4MGDQI}Fbd#Ri>N&a`#!sT_^u7m@0Awi5nBbr-*A`-| zpVZ2=0orzw*(8s6nPDRhYKd88u%G%6{6MVZD>b)_VV6DG%H_X{k z{C^~V|2lOzAtj7mk5mh!G&o*%4g^Zh$ph91f;HqxZ+dpLSnJxMQ|J&CCL2sX@etx? z2Xr#K7dZZ`&TDp~p3Ubp;^1XWZh%feCvTm5&Wk+!nFrr-glEx{riB+Q`HL)rZa8-Z z5HLlDbR*!FIO$hC36kp&QK^X2QS5M8O8@O~6adh`xpNmaqj;r;51~Zg^DS!Er~=qj zVzj?*E36t?KdGEG9CSL&*abmi3kqmj2Q{oxt=)>2t@l0ib9kfD3R(UHs^JypdBAih z7hjaq8vR2JyIbpTYG`@)IBq8sHGUv8awNcrhfd-9p1KmBYexZ&nxwXU8hYJ-%@uEc zH(4Icz1_YbpB;2wTT6?z>dKL=5CE|7#m4JFWg-g@EU;70iU|2@Pzgb*DZ05b*DMXD zm+X9L0 zF#EP2desC|HA)KJOrfnY(g-hjb{(lYXl(-1M@F5WUV&-%j>uc+h217$Q2~?*vn2g7 z)64(qHKpWB6*$LH%nYtM8e7YrPD=h~_-*lDMkR&R-8qxrIp_Tk0Mi?y`VyKg^{X+w zegvh7XVhqSI71vMQ?hpu#>7k8sc_b*FQFY!(do6x9)DzR`iDy_c{hm~d~ZF6m)CoNf?BD1>{X6{6iPPJOxzSDY4>rP9XqiwHi;oTiQ);KsBrIBH)m&UK8;4_Z9kudXXFz z4|0D}C|{o2eU+wok_kWwIV7v@9Lx4VA(1hR=u5>o(k2NxXRIR9(4UYVi~02`&GjS( zdPFj9`F#>HwlyG?3EwT-%U@ntWHyTimv|OW1sbHAu?~ii!uy zO%GoU)}iRx#i#*OTo${OELEvuVc1Fb&rIz=g%0CKUE%++b(T?aHC>wy(hwlHdkF6C zPH=a3cXtAf6P#d;y99Ul;O;#Ek5QR@i1DZW`_cAO-k zOP`CSgGye%+`bgBQIT4bInkLm#XAc8O#t-h4Q$UJw}Ec)*P9p|Hm8aipPGMa7uN86 z89}s}LJPlBeHZXlRplYB#_1pD>5Ty9WB3inma@BJzoDk!OR2(Q4-hp=AyzT1ce5rN zLbNBMuD~xc$a=tr1hg-7@)c@o4}Cr6FK~aU)kkgu7)MCB%I;G)?PZ3Xj8dp|b}-P4 zTRay94?O81$Or&7KZAOejxXlsBW{;fKwi+kDO$`87hrY7O zEPova9ivr-m7!>U3ZX2hA~xh|2B_Xj$X=B`$71AEQ*~dgV<@%EDjY9jTnx+emgYJl zzp-~(xNhP-N1!?TK`8$&=)>-Snek{m`8=WN^aipwW!w9z&sA{7i(^wF&!oBbfwC^K zF13)Wxk;;%ag}%9u3DnDU6dY3hM9)zpl@_Qf@}UBo)fj5HQ zUV=|(B%$$;sXoajKO!uro&mea8ApBDmyfF8$%w+#D|zaWy*K;4-tA7(NyhRuzL!zb zbIrN`PMn9iOE=2rfYXJ%m6on1k=XeFzeMjEquQyhTsbc=4kK$n#lsp%9?g3bTIq;- zow^uZNd6S`J0>MH$G?bmk%RRCUbM~%R<~-`K7f{fX5XY0JGy$5FC8K3KemtO5 znRo%;s{EC!$#F<}(eV;5HH;0bn`~TG)T0A={dEPzf9@{imyv#}EVtX8e4MO;x!9{t zxGR_qc(`5uBTkXYel-MSrPujPVKo%@sK|-?eOtd^uQu%@l6MJ_fnSTb;e&I@B6p`` zw*>@z^DnJ~#$P;LBPOyjO&A)IF)Y?WCE z=FY4cI*0ToJCEXHpX~?T89C8O9#71&tNh+ETpXwdOsvP>7m1NOzQHHst2l&5>3W-~ zkf*Sp0DfEa=f8BZC zIT5eqRdV^3czhOon>feKk1B&?)x%%3J-;T&|D1t6CPb~h0MyWIY}{=BZqUrs9jzp2tH^wzeTLPQxPYBv+H`MYj9V6)pc|qRW@)i- zlz93hnJ4)pzO?Nd%)ol3vQ*-uenDgFpO+&0_ZzXh?AVR2*ZY~b|QW(RU@oiYm-aK(r*YBijeQNws!F*M=4cXS-3t`_E>kj&Ngccy57j+?!YA>s; zm}E!A;t|JTv<>$4R+xHry_tt$OH;FAJa1Dgb-a&-B9vz(abwJ+$(xWkiwQf*&f(M4 zo?CX|1>Aw<1!8g2IC~bK6!_ZS8DGmKO8Pu)db z)kY^LSLr!I%gVmzrBbGkD2Zd!80Uh;0WZ~z;PWt5V?ONJ>?QYVI1P?No9?}nFRT!E zakD^AM+53)%_PrY4ss#HB+BBl%h*XT-b~Bqg1pfOd=gD$i~>HhrT2n!LK78!p04doP|uRJn`-j2)h52~23CiIzd7O;tunS^44q_$ z&W+D>zaUo9T(pjm(w}{zTNK1OC|f%~74|nJx%(D+NwAJN(LU;xwOb>Y+mYKBO)}Q= zBV2-|`Rg$dU5P13K>*({!;U;MqX^eH%$TCY34tAB-<30PkO@}7uE1WLme&f4V-10u zXg#i0zc$10Acfv^A+J3eM29?KlA^IcNLrANhHR{QEgYLEs1ccN>~0eEnZz*WZgIZ-m2TxA$(-*?2gP;a z%T3)mWT8f1yppt0V5Zz&q<%+%w1!8RlbWCg(N64`$zYFVtm1X^goreMt6gcAZ{wGt zFrF2lYojx*zFJ0G1|GC3C7vwl{Xv?jk>vQ9mE3WLbRGWKy+SZyvTpa%*>X)h{-{0n zx_O)8?skSh(Gf56!`_tjJaL7C{1#TFYwRVe9nZHO?IK zmg-g`ulQ331@P^Bzcn)4MNWfG;G@c|ZgI1K5R2ptWrR_D(fq=ab){bjXT1H^dU`nu zKhC=2f|o9(F&__@C~{2m$G)7Gw@mHoMl5hLEao1mG~m z417TO_Xm#{(lOVtNFL5Z!m=Ahj0vAUa+7RYZ}bp*=13t*>T*TF4D_ROgtH~fS5(%k zn$}XR){=Sk+v+pkCWHe6)iCq4-gaXjpxh|i~`iNEpc)Fz9Y5u)XY(J$S`L zyx*Y50KLxpMB?%ll((~j>3e-M$A^O^@g0MQJ~ zw{r}WY2aPcx%b3w^ab-plNzbeRK9$=($BC*LQn17Wtes!RVs{4TuU+>+@&&_yC!35 z?w!GzfbtBq4i5R?DLueBh$~-I_d=0^eNz=D*#P=1Y^Q^Dk+cas%mnGtI zZ=f4pC=<0bu>E5%)3dvcs%7yfW1#jXO1J|_#6melT+>#W!qd>cHpCZ7q~wFK-g4?~ z|0Y_p5sP1rSOcA$Z650&Ge2zgEToYzXN5KibI<@tuuEFl%PINYKTegKiN0DeB) zzO&Cm>nB5_AjvX~u!vyhl~#HF(pu+KMYkGyQ=M_bjjw?$ft!cS#r9p{n(h2r&ZAuU zpDz2X#~97bk!FN8tV#~huJTQH%A+C=3}x`R^Ok;6qTMOy&)qM|3jgVYdt9C<&bKJQ z=tL1yvrDCO-raD|29PGRE&%P@AcV-DU(+y)Sd=`;-5lyj34+Kq?b~1^8REY!MVl|3 zWI*+d>Cx#hTOmw)>BUR1s@iK}E8>nyqoTQ>Eq$qKXV%*rG(QVTv#VN4WnWtpq`oiD=LQki>t91L^MJ~OA@m~;^-b)cswwAYctmky?ma} z%*fznSP!ehbtW41G}k2sq`VeUY~|$XOr1IUC3Dp3inHA@ba4CxsV>%P<|&gEXUAeH z3=4!3T{P>zGq#r{+ zcaV|Io+>f#V@DzN2C?b2EGZGRU#i<1@2Tm&jH0MEx;%0w{JR7MiA$b7#+aHXB>2k z7H_#Q*sU7X*_>0&6d!04^FD@#cQa^Qa6?Y!R*)&D!+qc4SMX~FP6jabGvjN6C@K}McIPl= zc^1+n6pv&d=31N-Js;^RKY#ELS5Ka0sU#0u! z+(G;5zc9#PrP z@1&|C0dFBGFLB2M6fEqKV3~2&4_>^2kYyXzlrKl=A>K#zf<+v|KVCN)aR!3Av>S#Q z$uBu7OVz$Y{#t^pN&wZ->A z!lo{K<)GUv$2V5aWlyMFlRgE~(dU@txe*e147eB1hbkOp)g3{w9F|%YkVE^qO~IxT zGI60W|CRKuM&O4+b3S#(qIp&TR4i6&KG#%s^JLQ;zgUN|^$uwq;c)h^Xq%vxA#;@_ zOqicm6)JaeNb%=G1>LiL4PRva*G!YqNp?<`_G~;UmGE+7c+s-^bSeXv&&(36jX!&; zQv$0w2srT9Khm&UnA&}TTUi_YvBK8?eVxGAo3%J}GSB8|XL4&x>jH~qz*b_R^b*z5InsRIdex{>{2 zTiEoSRaeWL)I)m9P!q=o!x<=fL=0uCp8PBXCHnV76J@2th%uXxYuTbJLmlnKcAH>6 zCAIXcWr0rdt+tyqf#I31G1?vr7e-HNsy73RTXd`OjM_Zb>^Z}dBa?RGroT1jjv{~_ zpSRsF@1j>(e>92Pu4Rh$r1L;9vxkx%4hfe%$W_Y_svtt2ueusVJn)>_fLLT#f}tr% zMghzBM;}RRp2$|6Z*8f}xZN91dvs%-JMsv{(3fXZ=w_EEK zn${oI(1y7lLmqk>941eAgiN(uynX}zX@TN&lycQsW05DEj^%aR4-9uYjws^hw=j~= z?yes&U-#a_LO#Atmz14ogMpN+k<88T+lZYM&*|;Gjd0$;9wp)AMd4h{d~-B;Dhra2 zBc@!I%kGJSAHIuB7$_j!uXgX8D9rMn9k`Mqg!ch$Hr4E57UZsLhF~)*GV}xcH}3BV z>)bI^t{PL+HZo+#pjWTX<9-4ew~p*( zUK@t!r!DZBqBC%kN@~7a|EvkDz}d$aznNwHOjIU72TZc^2@3;r{59k?`&+L?Y z$Rb`TnynlclRq zlT`8p*C6#6`^>ZWd#X&o>p;6l3`aAOjnVe~cd_e^fK zPJQTO(`?6;x!FfUDC_JqDiF!VdMmQF6aa7X2I(&X-6V4P)?M4!S40-Tdt(*`-=hP( zFWvZF9{sY?B29h3Mx~~Or>XoWmlsYN?FdGQ#OyBM)4Lmui>aN%`{T~&#+$zWYu)S1 zs2m|j@hWg-N>KVxttvbC`sMxi+w&f9>*5SkWA07brj& z78Cee+sE7EpHtxBHHM>Zo2|_e_2?5sWZ3u;)X~ihXI6(q z5@p4wLVl*8LG~%-Z|wg2Vq_@52YiNaPB=ea zXsC%f`na&_4{n=kjQVZ5VFZ3|SOzJk1HSL4pNr)8Ui2=WQL*t zN@t{RiLr`L_=sj2GaUd4Amy`4bVQ*cD>Nvda}3;>3yJLUt-Lw`6UA_RWZO!oo2eQ7gY?spR) zNYaQ};Od};z57WsJ6_Z68V^SV+$0W^IfULFtUYp@`ks@OU>zSTeJeuKY9L>0dS>C; z58=3DMZFM*?$Gg~krQR6gcyyHZ$BuCI}M=-@W&Vny@Vx9aU zjf!|B4xH3zQvQ2Xk?PU8$=&|xE?;&fj@)l-!F@MoZdyT&VM_rFjeIZummdAwP_-`4 z;aUUpUSn~{PR$q}sZrTt;Er*ikE7VYl}@d{0yOC`QsM)jB{>^(=oRFT`UL_bXw;AP zVwwdQpb4ncfR9VrtAk~*ASQ1<=ZPyEIB7-*k8aNHx*-0tU?y)Xx$Gon;0pUTwo-?bPlaz{ zy@SnjY_r`3akS!ez_Ms)6LJUt}1s!o%;242;^H%t79EWU`bTJ`|S zfb(liKJktr-}^**J|$k6A6yO&PDlVM4mqGJ4zsa2h>1H)mioj`ad=CxmQi`%%bVd@ zf$}M9Q8^$CW(brDiI~k+Kmy!F7INY?l2C;CpYy9Y=|RG)ONGoEF69O5Vs)*4@*_yi zS!E&JND$jBFyh-h8otYq(F5r8cQ}HWpEB7v7H=MbRv6EnaUHegD>={hs(u0fn79YU zskLXX~&15n}bJ5IN%^3@U2nFOco(zgl)}$?YrOYQarcc;(J}SQD)d;6z z0-2C*5*uC@dmSsM!x<>B5bl99St>Q<4F^j&823zOK-+h5`E|d_Qal7K-3Z_7FQf_w zsMSK?bfppaVoAJBBX;|yezV2zk*dfpQ!caShru6~>3=ESgO~J07KLKg<$MTt48At! z3(aa$UKKsd-*q*di(ct*J-R%FIL2uacRC_H+TlMwc7+KCb@#g)W;aG06A{+T_%k10??u#7Tv* zRx1>y*me6Z=S@a5LGg3V_NymHu26vk+{R>SkC-t0@V zf`#bPt+`Mm{SCuq_eP6ot&OV9H0KzZV|bP2g>@40mhJP^_+>D6M46wc1{)-5w*kd< ztmJSJ81dNsfc7&Id+#;=Fnk_=>$dg}-=Tan_DyB9VHk{ZXK0byH^#;cp*N{--lNP7 zDuFk(&uO%m{34b9_34`J2p^oRmNGvWW_oYUeDuzkKxtF5d8}W2^SC`?f7iWPvtPHT z+NQHWaP4CNak`q9W$l$-cb1JDw3e#VYa~UNjSQ&m5$Vl;#?QeM)y5Zo@N}W6-&Bn4QyrbGXy^uLb?r2BC63lp7#y0zKXDUch4HEKHs{>$5 zp}OuyL$}5DJ)UY+z$4yi<(4}_&_$ppe$!$A5OAT;Z+CXFbst|yxzkufzqSy07P)eY zT!r~TD&)h~7EMG<4HUNIY5kmPt3b;5&yIa{RhbzXLz*H*JJ#sFSQ@GDyb;*d!r*Di zhh6@5U2P%GcHMmYOEirZ+#(Joojh>vxe@>hN|G?A^#P(sEA7Sv&UwYDbo4E%`0|ex zXtK-^w?gqxaKB4_sLcu+a9W#v81Tqn7GND9jH^v%Zk)Cz%xU~QsnRpB;$t|g`dtAQ z|3t@dmM?06b8$*{hbTcz)P-g@u`oDWnu>})Aa0kz7Al+k`n0Y{1ty71)zlxz`h8Z~ zq-rjrCNt{LH`xUSA@o)lW{~(=4BCT7FW$A&%ze(Kw{${=W_O>nuBt!Q_nHjgF~Rz5 z3ne`rQR=vR`(t*Hc9r{?yDJrA4FTW862)XV*zaBHbEKKP^xJ_nFwg9b# z>M-pFq^&DX+s#l{4`S{;22oBq$7+)BAL|H9!H?KckVeQBR5M5-S^fsrNX)i(Qaqyh zG0~m8`lzWV_!_6=eNmY@h=nHzaka(TtiyUd-ex%SC7jlYV+<~T;mZ;dkwKlMWn3LYpY z9O?bPxsJgTd>)N=$L0k7N$U{3I*wQOXD#6 zrdzj!Z5R-(NrQq%y{q&KF>Cdu5o#k(7m+P)AGTX7i*LHjm*;5U@~ zdI8tjVCTz+o_9*KmpdJOEnvQWjyy*Wsu%IfXY>88{Ymx|m}~@0kx57r`%{tTJ1p=z z$IJa5t`N#da-d>Xh$FkvrQHlmfc=CrESm@A@;+%=h@DH*k+Yv1Sd_n15TJ#!z%RDs zu+e!n`P5GIE(yswMkIf2wXn}hjxr%gab=~#$=JUAi?9w5;0pe>O0qVmC%^t+jh@CQzYnmmOUuisIkK1LwO{bvw{5zA z_!-Dym1*`N@-r z)Ow_Ioeut&GJhk=ttq=}}CIWIwm?3vLJP9odh}+I5xx&Knw5tSlCY4nrt+|B` zt|e7%peh)+ z+wMjH&xJr2njpp+*ZhZ>O!y-DS-zSR%=;Z&7HDj)ZKX#I2p|v38(sC#`u^1Fo8{#> zD*#c_{~%)SMZa;F z%Y*~Ac`1jHWx}j>D+RW@!iOdm`>ADnsTL=4eP*Rn#mvv4RolpDGcv>aUiO()b<^OCOJ=eYuQbi)-R2cwVfiPkZJjLMJ()PmweawR-h)NNYeL`%J`J#rgJonGIs6 zkO45|CzqU)%F*bNGPN#d5!~5`D0fQuret6{8B%>`MH7K_8_eI)z^Q!b(*+VmPy3>U zivQ`Aj1qWWniYhN&zNil-$}Z?dH@CQE|r1GxKA&-%^LU;z>|OGe&)N!qI%p&Gw8F( zL=|LM{HXLW$4Oh-vnbG5^+M2IvL<6EvSSu!rt2DpdZYvGYHyUQ42vLBYFNKYQ|^&N z#5Zl9{e+LR^AWqc@kV;7>1V6bGYZGt5W}5=;XDw=>U~@iXB&%sc%#881?Z+wM-|t% zl5Be?8#r40bsg3GH&mCiR;l)PDGPk3yulBj@NxG_Ix>IajdGMk=oA}>Lywy;CHFz6 zJLUFF7q4nSH02f9o2fW^cl8?<907LAGOS)D43J9_VQs6EQGrJD7c2V6$5;b>zGyvP zbpb%@o`)zHiSt?sq6PGM0w$>og=^#2bo`RvO(|50H>(z_5}E0^F$>G%=PwqQZGJMF zQ19l}AY$-#z4rpWl_<`p_t!t*xsp!cQ`MgfM$U%i4Ey(=cEGM>-?W(vpu_vyUe)+} zXUf{?3($Y~EL&dVaAsdGUZ$N1^OfO&BntQ`=$Fe{=e{XZvJa>3_3^>BlEi((@rlI) z;q-p(K#!pzFZ4H3v$j|>B9(oQe(PA)u3j(tZsEP>Jm%Hs{DnZu%AcEvc2W-lc=l@b znA?=2p4+D2r~1q4Hf$47%4Wub!^x(-n*O+6o<$_# z23N_$fp_mS`^W@>Qf#O*+l6wu8+R@cN0#(8VdY>`NSw9wBTo7gbNCB0w4d6C4i9Sz zFE$m*kb%tn&L^h%0r9V~MiDI)J(p6Y5>il{X`F*)HwtI8vR{}O+u_k(adFkwYG>D& zZs~;%(p<1o1WnJ&P{bb%r!_G*6kFAwddg6ILL-6@11eS+SnK^iNaa)$?CiAxRrL-5 zoR%Ii?1J}A8&>QVc=`Fsc@$eF<_g=7Xq-coQ)M{cGG%kZr}$$Gm$%a*VrbZES&g4h zn=)EuS+b-MvLH+*+2Q&b=Yz$jaUg&1qXb_BxCV&AJKlfjV0*3#nv0S$9Dqf*7NmBS zzjsESM+RrttZ9=fPcD~bH-~8k@)=_6E#_?rl-h-be<5k@RVA%0_$2>po82B%y9A%6 zch2y2lP7Fkj2ANRLT@yHn3NUXDx@2(nrvI>i7Vwh84d^Hf|whCh(BQVXzg1G2~ljf zn68kDLciW&mL;OuZ@~t2_BjI%+h#V;1#i$@?1eR zvzmk%LB|Wgi=Sl-qSWQ>dLe>1K<2(@Ko2B{OQoOtZSxZGT!k>IDASkajG5Xbw z^za6dJp}G?(bc}|>5G(8(`y)Ipboc=$I+Wa_7>SjqN)?;pJr|Ny!PWphkuE+v+D`( zp=9}Wj2^z!;gH0eUsTJ3qd@pGW>x*i@_q0EIhmF0>NL9P1};V;EYKcmV2@HUx4|DC z1FBOkl_MHvZ8M!~9BQAbzIt%_SZ&80x!U7x>nn6)e&runhcRe2#b`rW5;a~aGZ^FJpd=~W;Qs)VysEa9)Vl)iy}1_&cJ`X4(}8-H1e^^rOQ zrisqM`qXx|$mafXW&~zJ1qhMnq*2?Ri3ylW3s!K@x_sl^&)dl}aD+=Dfw(@=RlBr= zyCv-%@wZ!%*yWCb{2ZmND)Zup;%M8e1aGIbhHomjw%SCYd3h$gM!Sf^TSsU3)9Unt zfD>(VMQ~DtBWwQ7zV?t69V^bq`KD}hfUbPHTh`0vRgLqtBM7({_IvIVn}Y*hkvd!0 zj~KQC3X}nXR_q$bTC17jPlY+l)Q?%RX-<-^vW~#BbCkv%Ctnh4K6hj(yiO5lgfRgZ zCU(Rfh)*@V$?=*??yT`e)n}CuNi2qjRKcTB5>}WBy%KkIQie{L6_GGy9$}JdcC^i3 z`a+_5v4!*eOW}YuJ->IX@geCZN${3cossvLU*gS~J+LHEY!Ega?Xikactek1kjc4~ zge~^%7EoJ}S&ZW{Vwj*A%x|OYT{;9V06=KH&AjA#N6*t4T(5aAH*zSWk7;Nu)uCFr zt=u)Cg&s5r>$K+1kIn81LCelDJF3k=ISb6gj2w&!YjMCa#-h~WEV|GciVS9+PXaDl ztDEAbC)0W%TUILN`9_*csV(U+qz?iC8pYM$E0#DCEC3vI8_|C(@U6GGT|IfQ^tM25 zVqtYgHvt%k>JO?d%?YxnKFS26Bx)Y2-pn5iaLyMF;}foK4l5_h`_SE&`ebcAw;^;r zSrIlN3yOgdx)#53_E%hgD_c7ZF&bN;rQ|f6C@BW{iy6&qOKR4+NRoLVSj}Zsx0IYQ&IYurRHCWKwx<-^($M@N>VjsIb47_{Xt|j)`l&H%Sy5NTRLfWMQ#cZa&XA&nDrsST#zuUaa(WC$rwm6aPBM7CxR`xJf0+ zMOJKtEXTf>&J3CeZT&O`$GvM()4~*ah1mgBrVeXADZ=5pO*R(UVi2JR+Ey}ppK8_rdO|&c zG)Pf|(O^I7Xa2J-O}oG4sT1|jp^)$@(2JbcucNZ5_bY-E(s26NzNmGxpi+m9Z*Oc= z@F16g+~pFL^qO#$yc+V$_WsqR@)PiDBI=ClK1p_@vgA$Xr}rC68JvSjeA~FVb^N zQEpv5qF2CyB&-jGYHzk{eAI|K1n7s?QY=uP<`_q1Pn}OLisiyLmm8a2clJZAvB2mN z+Y{pGNw7Yq3$6_ul3EX2CsAx z^8lCfuKid{R6lTa#Q4vl?5{76Pna~Qrb*te+aDqyzG8)5p_urBH-zXDmIEm~;MjPU zj;#LRYUOXZy7Hmfdx>$bVrIshF7){%*u+tCq=q~H7!b3VbDl6Sk<>2w5J&pm=P!e;$E=buTjLE~r zZxtU-SC`-y8~3~kE)?+Dy8n=QBm)@^&i}50)S+Qi&9kv7gGNJ7#_8(@_Vcpn@j;R8 z-(!oqzVF?-lk11LsTMO92dS@Ik+pHG=hgcglCU;weN5G|M}TcISnI4?lU>hyk|FW3 z2~FTee?Cg&1hu9hTO4o3K)Ns601Z;Q+H@G~rcaCHLKLgBlKE z97KcKGz0ChFn;3 zlLXf)KIbsqB?4tH?`26W>5W5EB>TTO-eHwU%f~EYly7Ft3U`UaHsMRRwfZI?O{Af< zX2ot5K50MhkQ2he_>{B;|6#vytKrDz@kW;$zbnr3JX?j`aT`=s zk1<{#{!J9}sMtMez)&$IXwv@I;E_l%>W|^ybX#AG=0thy@DQiv9Z33qRJ+Q4GLAh} zouFx_G)n*uVm_ttXK^D>Ppb^QR%@#g48579;kO zR8HiGCNI7qG7#$TjCJKo*hd~b`!nXZcX0gUR8iGNht1+UD_!Q~*VoUC&} z{VGb}+CGAZySiYk-CzMLv6=IX4Wxa9&M_rIGU|74U~a=>m0F5$M#w`LpWn$#)0a}AnWyAX-on4oF!v9JaBXr z==zO0X3JH(zw(%W8VAeYo$uq+`t2sPd}I{xYbD8VJLx?k?{@rrr z!#uW>mgT%z#?MvC$QLo#8k^H{Id`4AbqJTPZR(=B0obp07J)dUTOZu5MI8i|bx`JM zw^#P{8U{PEXS})Wj8&SGRv({}YF)!{=B~f_&40n`icC_AF1fM(D*MGxkRZOiNyf4n zi2pj9*P)p}fkZk(uaD|YlLyE7yGLoCTArO!$*#&rT+`FQlK&``#%glw)X^)5`lfXA z{#?go)qUCD&LV1*99aw^SxD$NaU99TCDKb`w~&>^DkjC=#yl=3e~ijNeMzjrz^^VA zb$+qu;D|*Yhdddzxyx+a^4^oZC8_3AHP?RQ2pC%$3V;`;J> zH0?8a%7i7qi{+}iiC3nHZ%fUQWs|_ns{!7|!*-+VWJ-rlemg%0x~C7S9-oL$Nck7B zhy(-xF0Tzw89;`w4(#{tAN{x-h~#nPYSCFKT;A4!GT{>14Soa0H3&IR&c2;I&Fap)+++ZXEM>MqQ2S;6?Dv`eKPd5k z)raCZipnZ+ZBpk4f6GP{5hw5pP_9CzBpyq=ftU?6oLu%OjYt+a|l25J6~N^cB!~4piQj&f;(~harzAEq?GohK)uw9_Bjmw3QzlX`d2VQ zy@Ow866pyvNj1GU-IG_$FTshsy*tT3GohzSwNHWaWytj#A}erin7?FQmenXEJ^$#&xUV8fEg>5!brlHu40ev4v(Em7hAKi;?z-m%@1FlYF>q+sM zajp$JWFF+$wt;-pRXoDhR-YA2;we8ZZs`%;b!j1!*9QC%NjB$yph*vOsu=4U*KIF#{wDh&o%YvZPV)v zkzK}`ZW1*=nKUta48#zZgI-o4>#vlh)i4U(4`1!{7ugigUjg1)ErUyBGc!xKulz+l zsYcsOyBYv;=dPQZZ_yq*8743GWlt2*iYSHzlXJ=Hv$!cU4uPRWAyu0?$gY`-M!;Az zkaAzB_jal!WeIB>yBeJBE?bOs$p>5yYnQM6VdNLJHnI$~GG7PU5L=!|L&d(91>(uL z9nzX%^gXSVmtr!VCcFO{?3qc;@}fGnnnGHb_u>GBU^uy9T>fhE9$HSf9>Mh1wkm|X zb>+HsZVNBB{ysqwy8}8noji{)`@)LUv7(PXQ0vI>@)>@d!}XB-2y}7tNp1LwKc}lN zaIc%<9X4J!WtG9l#eWogLoiEE{m`tq9|N3Yu7+af}{B6a`(scR=EdUL{2BQ4~ zJqMzL08lk`O9QAOKs^uunkMgeXhaB*JS2cRsT$w|iiQGEgH#~^_Mk3kuyq0fFa<%w zfSY(g0%zs{yEB z%T^Qc0^0v;b@~8YKtpI?M+R*G3IwPQ9bCwW3TOezV*;o^C}@CI&;%y)?5JY|aDxEZ;sa=#UW@_w z5Rgn93Bt%!AR$x0B-s9&qmdeP!4I&3VETKw8#RdA4DbZW#QGN!It0akp!|ms=RZU~ zGyWe&oc|E{zZr3|{7*)ltW9`C0Dfo)_P>l~K|peF@csq!hXUMt1Q|dd#770T{vqQ) z4X#$O2dF}Ta%cc_Oh(0^GmI)Qm z1d`?eKO2}r3uuQEY$31%)IdU9VCx?qNZjDquA>9&AwU&8;KpDIte{(7umz?7{?Wz< zeh4rH@cYrv4>q5T0fZ1B9RYB2FoP*@*lR)nix5nIsU+hAY$2JM{tkxfKOortfNI3k<~yG^zmhH26m) z$V%Wsuu29%1%E9&O~5PYP#N3>7>X+>Oci_|uu4!NK<;YbYOqS0K(OlI9>IK?L8=;H z1=9aj$yZIVBUmL45FiUJa5Y#Z8X$o7-zJ6tHjt1G*aGt@{&!$tKHw*V(gRTa0l=)q)=Q;_u7wF9!C1UWWffp8a21U>U$eK(cc;IZ*=`!Pq$d zqM`sA4KW~w!p%81vUM(zzp0#ukHY<|1ik+02ltlfX(xNGXU@K{0{?1@BcDL^a0;| zEdXE)0b=>~x6NOX*!qIo{38-MKd|S&%3uV73s*t_RUmwS@RNfh{|Lbh`nyvZij9pK zl#B5Rv*{!ZK#z*}#xlUv{XpFH3hNr{3%W7@U_i1k{mT=-7_fyx@{IFQ!0+1=af>9x z|1XIQc-u30=_~~_GZPc@-_^6k;12$iPUcL<&Vir_^{vuCIL81DW1nGT_}9nJt4hY* z@`SXE_E5f>GPFn5NAevy+>Jor>@XSdj_Zs%dP*x=p}BEqi{Y&?$4AHHbP==)$r{WN z+*g|1gx)Hwg_?DEY*N4IkD+%;ebD-4Vk|_9)Hf6h4LtUR1wzn~c=U-gw!Z={v4Hb- zXd|1{^QHb21X*&Ze`we;94FhxLW)G}tHgAqB$V|JIU03x0;jYS6ogfGrqlZ6%088` zQB6uXl@NLgYbmxEx#sh)+G1v1a&Qs|ldp@V^OQ9A8-1L$9&9Cxa>kLg(N+wY#1o64 z$48{8H82UDw%d34_1K-vEWhfkS^u8N}bM{zsqxEw=K#fU`8LSe5o7(950eV9Gb z|3%b0MrRUiZNsr`+qP}ou{E)6=Z=$!ZA@%u;)!kBb~3T&%{k9m-}k4xYwfDttJbRO z-m2?bT!fmWC|qf0ip0TuWvFpLr(NZ5Ff<28Jf0mXm!Q)~EGzM!HEPMDvR%%LwF7QB zC$PdFHWsJ7QKUQE_pUZ+79Der^+s?KE$C7{V2#=86rjnL!&5*P{4q&hY(z?QxhK}o z{4*yNE)E9ERMaFtul9{y8`EvmI72IEqi4ISNA^>&&I3Ee(TAemJ;H)raB+9nO1;kD-d8{2f?o0x-RW8usWW$OBMg49qr6JYrBxX&(N zb_QsTin#dW-u}MLI})C9U2sm|<{A2L^lW7+Djb}YJfw85L<(v@R22n);t7~#Pr5o& zYt^0k$$~yb{&(oh?DVKA*&$$EffMTW&g{uVh@be4c}UA}@1_VMMEfFm&CD#2GBL10CzG&8!jOEcRD-TVdSzaRA>sFI=8~R*+ z_PF8Mw32MxD8gbLZxKCohyYaGE-XZln9X>l(m5k1&rE`uYC*iC>gyKFnSyd#kvDfx zL7OByW2IEEHS_Slp~M1_F*6tY=$td7uM$j<%F=7b?@0F+`|aik$lEQR`3wKUZ2M%p zY-?j-?e$^llCv}~V2SXdj5^uDpjp~VnAGq0e!JC=kAr+N-L6_AwlH%a@ z)FzWF`SL_4Y%8hfg;}5+_W@UTD$8*Arjv3g*gw5ZTG@eLHNF0cS{%rh)J?C~I;}hK z>_UI5@xudzFnzi{-llG+u4fSir$XW8E+{0%+A|$Rc_vB`0elQN4f5PG??ab< z-8;-uB8eAyPteKNeV2&36zTGcHldR+tr6wEcJ^@=$|{SgTOOCmnA%kSvJ5!gsT4lbyEr?*DXzXFi-i89F;^!0BGe@yfjip5EKt>eU5#qUVP1T{G4Ma7dN4s zqX18?+QBof6&xVs1c)u^vIR%EIfz^zASNdmU*=$af>prLgbR5;eRX6N*Qy1B%K|#G zfy-h1I*_YPb}fN0Qq5(dfs}s}p=!_(UJXomnLdB9M(PW`?`xmU$@EZ~gxzV>C1})9 z%p4r5lGGQPA7>$a=C`hur~B{O;{i>0fd+lT)uonkId5QF?D+hRoaa;k^ry%0KLZfoXckWu5g~{ndIUOYGsn<~ZTxQ`M@5|ab5D8n_3+dS zWtE9DIvMET%#h{zNs#QvH6#*lD2h08-#vmQ$`O&gBFN=kD5`y_82X%mG;aiqVU0ZI zUjWw~;aHYWG5G0ktn5wWUJp~1G;%CU>eUlO{}JnohC<5IEcPIZsdZv@{CVR{U3BN6B);NHJ^?HWXb{fNL2P=>u*Lbr;Lh_H@Jk|; zjl(H0D7w8(u6-!U9a!yH_|ny5C}KR~)VQ2;6IMbBKN!kb({5$79oP4f=>YVUO@gF& zzvhl^d;$K6bWF0GFQtt+iTFI=S>d`lht2U-)#pGSTfoaKeP zlmOq==1bmb&*nd4+|Kg0gR97TanI&o$G4QRm(Qho#LZE|o+^SO`R*lC=IEUb25|*( zS0pJ~_M&Bqs`fh~CI1a+pkCy-pp^@rh6O&exJl2ACaBevFB{jsnEq$Boo zeet#zFLT_aqXh=I9!Bs9&;HKl0-jpSq=D3eo!;wz#;(aRS_i-PZ~j*^+_#I+>D`dR zJYXE({w$3Jj$z80nqeB_g%prj6Cgkj?Wc~-@U5hA^+pG<$6Cz*w5P*CHEy{<3mUhp#=$SEGq^)clBS;t z0?1Pacl4X}=z@E6)-JQ*=)#Ti6=PpVN}L$hnp~K>j4C;W#|vuK5{H&l?ON7}mJx!b1g9R5J!s}p%V0U_&{qQ=KB0W`I7u{Gr?E3ZGSNnV>7+(PG|YtyPP zFq)LA)6da=n;FsyIkzj<0uI_AlRgVe45ENoZ8}LJC7;_7YN--;3F112pZNchfJ; z{=|Ii>-T_s*M}6cdc3k66e9g#U8UC7*8J%yrgM~k%Q=F#{nI?`My75rS6lPhf8Ha^ zzfjLOKMPQ`N*#{*^z$#+Q$=>6U4loLbCRxcPO%mab*6hv@}-7;@+M~+l?DjM8zx;p z+-ZuN1{5Ey0SH&6SuKp6I#Bk9h7q`49VkA@2xUEJ4E|Yb@fO-)`Ep$d!BRMXf-AJk zwa7H#XgfG>E0T+s=B^+~g#4FuAVD7gi>aD`X+Rl;CtGh{R%*H_XKlB|J;cn3D7Qf3 zU+G`?B}|szY0(M0I92P+zCG0ZD2K>Lx=a}!tP zAzy`m$pPA2dDdUZLX}bjGCcD|yh0VJ|H^1q=3?2N=sHw5uVl7Xs_`CG(1$5)i)`|$ zg0r(OOz=5ZH2M^#JY#oDExKSFY=)}>acplyCJ7_k!C5^?j*$j8g(7KhKpenWkAC+? z1ZTWK?Wu`QEs;s!y;1;-X5Bfu}D@RAX zu#vDu$$W6MEc|yiWlxKJZ(Urisz^ou*6`!=sK?7IPDxP6{gpi~@%}Gu4^KtK>qyxL zSSi&BkU0O?dtc}*Fs1T_YZ*zV;*IGr1X+f0W})(~pG^AYqd`W9v1*(?>7zh~6hLWr zq{DWR9k;ygrmt2**by%UB_(!cHXq>4#Fjxqez>-w8=U3W(y-PI6!x6AI|;d-a=1UZ zA7L;gKpt4zcT`x&pQ2t6RqXg|&zXwH3(%ee-cFP-vrgJ7DLIf(&$ROg$Q0)s0ze3o zkOJh}5kLZSMHPKkZ#`dvd=F5c25r>;cUh?-{dos(>B+nk%6-@L#Ca) zCz0ZNt>@{t*S(k>jH~C?z5DQp&Xr*YtD+Ym+Y{Fz_!AyHa(s;n_J{IqkIk(&uLki$ z*c9bchjxfycrZ^8* z2Y|l=e?S@d8+P2D>(Jko+%f3DcsT>XU;i3hM1eEIj{l2dTl> z+0y$^!HFQg>!DfG6Pdqr4Y~%7n{D4Hy>%qB=})2yRBH3C+DNLBxl+ ze46ZO7L>79hbzzevD6+OBRUoWTgC4v*@bbVzR1is=|%2vVzBlp*u#_H2Ru!0{U}j1zL4;P7p1>q#x#2IC;=Nj>*t`bhR86lJa0P~*E|)fj5}M)4;c|B{`) zG6qnjY9~>|M!ALuZa8#6rgx9Z}gZ^9n4z{TyDa3_QHgk=?@%Nu7vaMuw)@Cx`O zv%plt!QQRT2Jzn!0V`RkSfpnIgXO7_s?;Fnrtf-DnPJ_6jk+)?@q0-$0k90Bx>d*81U4^qTqvPVGVKE^@0w!fxuBdAyurNDU$|?TbulsrF2~ zTPxfN3V3|58EYY*De}?l6s}*xA`V=TlRC?RV}r8%@!}7mK=k`O378C6uMwz&4B1AA zsy@%bGCV@~a4pobLmHTLhWqKAGBXkIOSy)EAi_Gbv~V02Gp-Us%Yqx9W?`_a3@0|3+ob##btMR5%faAbobg9tr*k&~Piw^mwvZboS zW~rwFAwcQMyta1ZtdLJQe^^-1--qn>24!oPwm3w%KxV#?RF4t7Ity(K=Sr(&!;_&- zrFvRkRStF2FqR|u`2 zBF1A99#f&M)`pd1!n!HN9Lv1C$j4kkVBhsnsjb$(wm+R(n43z#CAS9^J)notk7%}s zq6PPM2>D0VLE{ux4cpRmBUvdwS#c$LL z0%txG((UgRfFYQfC=|@|B()OV{IK+KV_)R&i}Hlv=I1xiZ`Y)jUFC=oA;s$2;Bx3*b@H+5gQ zG$kG!+vQ{p>9wCSU$_fCR4rKuYO?D&eUrPL;{?%qQDP>EQ7p~tWi2)AKGI|7A6WO! zkxeD%som&35#p9RYwH^z+jEb#=pZx_Z!eZJxeY51Y@_z0Xf{K?>GB0c|77Ju;>b+d<26lxO zJH;b(8n(T7oggK6&A^Tt|NKF8ckCi`yty>tm#X#2hiv-i65Di(bZo%?JZ;Hjsgb-k zLP3iYb7lpIbElN;F`E9dPqS#t%&8S7q5952Z=>S>u|sDeyI0)C6>RcVdpV0id0s-k zrBI1E$NI9e?w~*vZo!G|iIh3=4=6Wo4^^~fxdcYs=a}sKaonOnOHdMWcjP2SWi=6| z5^1lP-v1|z+mD2C3*7UkynrEsrxcw51A-nkr5;?X&@VPxDl~I$xf>TAt>dFEwa6rV z{t_pj`s=j_seRSyXjsr=+o(OP=w$lv3zFY-r7F<$Y79RN$X_b%I*WgY2m(usu<(hO zu%F=~@>5CE;wc4ci&yPkdx}>vVd80MPXlE8rUvY3MTjdQda}LMok3O#l#N^#xixf{k{*Cx1(bxt!>grOGYb_2w5=N-3mc#d;GsZf*MxDhb`W^gy;r?g6 zBj>8kUWYrqZoR5M-U8H*NAQ*pu|KdgWM5KdOSIajs})q9a3&0Lmb*!P+$2s z;(v9oSEoB=W0tt;pY0y>XBC;5kIBRvDRPl%aW#FPaVUK*hhd+BfZ#c=dbLA<^= zLm&w=p2iBvzLD#Iqj_r6nonxvUkmkTK~EGQ>b|+?p|80vk(8iB@0@2&h8XXQ;Wyl| zEh_pWlm5=;8--FaiKcZ$bFN_F{WS}*^TLm*J5Eb|AsTRh!V*I)xHO?E} z1k{86r;PW%*&+xIZf@59Vu`lK5;k+`dk5|3f}ef}H=Kt;Nayf3_Ce z|JhpUvCL4oKwW!Bd~URF%!bk*;m&y*$-Nv5c$Rn3`2Q z({(+T9+WE%N1=%^;;zI9&RPR|T{G+{A%Dlqje_q`iDk{}g5{$GXiq{4F*K%CbWZ-- zr6?4SLKWpG(4h#K_I6iy{gw`@zRS^w!QEly3Z&*w1&V7TtOxoNkl}b$6*_CzYmKpD z&6Q6|dHG6G>FVrx*)E`J{&JEf!tGr9HkwjP31xM}`_mc} z3OqhEN1CUAReL|k8EaxJ0d<35Au;)L zJF>8z;+-`KjVCnJ6A8?vSjD?O-dP>_rV*2!B7W5j7CjQ91{b#}xN|V$_QwNnKS!pz z8PFS=liacaAf+wMtk;yx0AeZu03h}KEdNOh%U-NKsTdcmW`vK5zLDHOMrD_Z@=u!i zNBOz*qh`_&sia}mdH%n*Ryk382q?QMK?#SIm6db#KYp*cE;CteIXT+VdvIfdLa0h5 zi`%xLHmtnfj0GAp*M&<6^yx{yRmrp`4nUb~7Y!9>j&Vs=UP(q!1DUw_YC@Od6afjs zgp-m(%{FX&Hfh4E8xD;nnW*IRgl63_q%?Ls zKfM=vQVHF3KlMLVKLepta@FR1fJ{$~X6{l3XhXpdJVl66J_w4`8UG$+G^j6{K=rG7 znAWS#UxuRp#+-WzF?6)>ReXKDVZXi~yWpf%-Beb7@o>0qaShn77;5bFBgKCzGi65? zlfwlxD_UAR(w>E;;SyFNx;P>4IXF7H`!-k!pL%<`W;kKENfe!!{ccVc0TwgjVOy3N zkNP7>e>iXNFh)3FIIPu#YiK+Vm;`L8yYpXcbAP@|x_;lMrZ1js+;yH$qMuAOTThyN zS}ytRD(Wn6Is#hS`VQWYp;-A6>yT8jK*ZrW4rz`Ma6)C_qxK+>UvGh>HI#FzyCGN! zCuFK2fdti59A|<>wR%Xv=s< z?kk4sBJ=v@Q8TD4fx)^g_yu`9eL&U=yZwAg0Ets<9wb3jCH9T|*`7;C&bIjY_iwaa z2w%KIx_Ei(_<%R&47LPvC=;R)#;^5FPBOVZWG&hE}r-B?AxHLxIqO?$&Bp&y(#jzm%XpnOlrAi2b#24WkS!0Ucs{3!JY z_Fvc)?Bu3HUEX%!;0L;RFO!R#43QSamFl*%%Ng2XrmN+YK zhi`z1{*L6d%#w>u{LCF7l{aBEJ;{=TKEJz=mt|OZI*1iWAOKDE?t~PxVa>RHWx_uv z*{VaqXO;loPu5P4K1jI|difjPBS#5v2OS*R)Nyn3<=l>wm48u?RQsI&c*lYhy(vN0 zq`+7I&)&~PX9Dp`2*kPVGFwCK*(X3pL2PDBy?l_f?j zEBj?F!N@I;0UWJ?=tg{GZfT;1VKK%qn{V4|>K2M*!D~$T)dF7mN!g;!K&B_;Ss>vjyb5qgy6#}Hkp0g;9zBltA}E_9d*T+)biHHeSh(;+#Wz$II8v%z*`O($*ftSZ@;;W#wfi6`8vxl%uD?#ZZsXr#Gd%n&-rY~ix=S>sh?teK-8vxGTG+@JNX7;eytZyG}?s`$-(?nTQ^Kpj}-##4uH$tuZnGti}q@ z`xXxz{p=~cZ>;%0tA?HBKlK*0;Jhp>t=|?B4Ja^JFpO3@TR^8)fEH7UG>f*MI}O^q z3B|m1MCg4?PbreHbu^K z=Df|*a?$Q+hCUk@btyhQvmE>~(drnQNr`m$!p?Tc@w)N-*{?1M9yG-qJ~XL7gL zlT;PsC<2fy-Zb30&-~1bWwN__fTgHa{0;cSHSvPqz~w{~ne6nDU7a1ghqX0TicvQ# zE%0A!w0rRopT!Z!gwhYst9~!RHC9R%q5$4v2&&#VmQo0?Ix{0Bw&|-n)t&yFY*m@; zFhO)3ZOP_WpBlTBW}B>UF3=qB%qL)JDsVr%j_3vDvYkikwKq67_IDQp>hx0t2JP97;%$OsBmDlf4&^(w1w z7NZ}(E)00f9t`S1C}AYlsgau@6Y|XPi;WD+4ORM?6^=c`eH;z0`2dXx%Wfdd)Z<^d zsN|3Y>@u3y#g`lZwWc5tZX`w2QwJc6k6F~6N&OUt#)2D4%qefV0{~thsIKJy(Fn(u z$IL1Rn<8YHQ#i51rIR!|Nl(^*U1NQ{{pI9Q?Ei}KqIST|d?R_MAu%7>P4!xFqtTq* zxRes=Nq-uh1uFP;=13es2j?>Y?SpjHh??@3bvrGGiG~F}Su&BxZeZJd{0JB&!z@<) zD+|(i7?#4^bd~TVsEkGJc9)g}J)A@5khZrS2YrKc^Rl%nnMl}l(`{bXt&s}toPzXq z@Vs~-Gbz#yZPRdKw0NY>s}**mSUxtvb22Z2R~rQFdtXbw!EBf+~LOG|6AhCA>?>CqOvw5(`OzC_j?~tx<=X$KB{GljkK`XR2@Z{Uk>zcu>I&W8 zRn@VagJ#a00UG;?D8?RMEtq4uzy_4t63X5C0^-@JAp^%=<`qh17EqOIP4wv@>Jo^# zCaGMza-iwCQvEX-6^pkT*l8U!orVW0(fx+9(dL-wqr_<<+c$#N7iU4o(6! z7rSJiz(K;DE#>?M`2GU-e3I|*bXvDmYyg6BW10w#G^)BP&@e2a zBq`a|4AXnMB+$N>m;BB`P@>jt!?Cb#f1izOsZGI8?@N5ShJ)M`t@$%_O#sJ9aoeUd&0V`^SBE zD6@Ih$TnD&ZLKG)F1Usl;8AFo|JzuucF#rf>1H9+AzR?ux8=)7fd}WL+dlBhq8X9k zL{i<)=-T*h_$Ds7!DrNnAf`p<%{6A^ff?NF?C0H;o)GY9uZYbJ^XC1%%Y_B?z34(( zLP|VTndWHHEw4AcL(RJvp}#ic$@_5%iGERj%8!#@Wv!7aWf(IwJcY3{f`q{C&AA4B z6iIZEBKo_A>!h6Aj%-1j99|ngrS?-HzFCBa1vhV5ejzGUvK1o00-@GKa z1ZEEXVRSFM3&geJm>wdk>z=X|7%BZZ6%Dt=SpZx-rmef(w}vy!Q-Ud&+KAk$U3$zF z?7hUDj&re1HLw7&ZGilw=~0NVpvYgf=i?{%35~`aEkMo%y5T+C#{2Y$&xK(5RKjlr z*`7Mqazr_*LE;=nFr;D;!x*%oaO&|~T3F{YF7lu#r`2fU{k_PR(a>~y;u9j@{Zr<= zdVuk>6L0=V??zm45AQJP7w`Uu&W!;(Up$?kLIjpkKE*pL)dkfF=I8>fVYLbzmgOqvt?dJC%ItKy(udK{@XKB7xr&jUvc0Y8+R~L8gBw0>|6nm` zp+AtHYcALajPzXx;YFS4JdrH~^{($l0HsB&2%) zXb-!pY)q3F=ol)V3{KOsoZNEGcwpJ6#=2H+kyu@BPS{`ZFZ4#NOd2d7=JaI2QZQcE zN%8gY-@l#8?F{5O6C9wV`=NE>OQ{%qVTXBFvGefzZw&vvFu#=eGEDK1V2_F}jCAYu zm%SfPUe9ruW$?-q_swua7|uz{xz7yWx7oMG;4Dqo58;Yem~rCEaM~3>C;*=e)%uN= zPzK(_QQ!H3)KqOls~g;?&^3S1lKbPg6#BYNve_WrIHXn_Ir)w!ZSJO9l4;D z?2mEQFjVXPf*;|mA@iF4;|z3WtWpmiK-C-uP-RbJ5Y_i@3AXub`r9H|cWySXHaz#G&+lR#?X*yeU^DY9F}LR2F|1p<@gq=*Ieu+Z1;f$#bO^4+gf!u zRde#3!aP0tq5B!^T5QAtsEK*8v$A@u;2Q~u*VJ~RD(WJ8dKuTfG1PpFG(~2vF7SmV zsAn)kGBE#BX-t-MD&PTLFY)hcb9nw=MNP~+ea}JG;3lzZYODd6uXGHT8qzfmCH_fS z30sOTyqycTy6b8eu%RWi#A(1KTu2N0zei$diPFuft78&$DQ5JrLsqbut*O21gI;}+ zJ=^K5IYqAFX&Qk@qkA_y?k}-DOWd|F=T-By%P2Y{g;W?=Kp@N*bSaay=n^62-i%jT z7J$FhzT08u7WL)dgkCcFG==dZ>eGnZu0p+O!hMWFLz)7wqX{W;A)wZi8gFAPe4NyU z8c%qJT6=)q`n`}UC9jN(*l?664Y?iv(Pq7KOTH<92*7_!9IVcXQ!Q8zH1rR zu9)w~>}Fq>HV}xEyU?OEPtq=2gv#81=p$u56_j;r7toGoOgk94n`nB z0|`pXh38sqhE_&MV&XKg3C3lI->CQ04{`j(SjJ1jK>auo^hq)yv|bSKQpn6o^=G+k z?=^GgDPsVZk1u178j<#?_XEc=P=zOh7>NT;ud#1!2MCGh{&UORxJn&G&Y$SE_Ueq2 z14}2$Uxx9LrQHg;p_5^|%GnyCbHZoTAO*kgT6e^a(`%*sq_K_jeOAnw)d7CfqFqdq zrRU8!XuE^omtmJ2s zVEUy5uz>vui%dh{yOzA8Q?8}aliv@MjT0F^S@MyEZPg^;R)-##xFw6V9g?2jDid5} zS`|o-5*)I{#!0t21`tVHLu`f-*+uY(KKgjx-usrE>2L@fX7yeIOw)4=Xqm*nBYZOKvn5!{_kd# zYi#vKe~=dNF#!qX?w}cb9-E(X_z|-Uc7Xb$2+#+PY=oD&2W1o=Bz}hNIFZxTqIkwO z1H)DVE_0MqD{L`GLl%1~LjTTS0BXR3Ow`#hhah(>0f@Vvh6}{P6dA*>aq$Yo?PP@W=O{#Q#$@-eLxwCsU^A;%hv2_QG@CCfcUsW4k!c* zQb>(4gusrq{g4HiO8h)wfDp1A*8O1)VIV`(Seja{c)0`D&{*X|eZ9je$tKtVb*THm z1hf~7gH;^C4^d=qqqv+*dk>7IDV;7Ln8iQCUmf=0ipE++wZ0YT%lpJC;|h#K_8(^%!Ds7vN}=H1nQ-{)So2 z&e*-CIrrJzWMY(^utD1lwyuG0%Zv)%UFk)W%GNd~v{=k#0kuiLm^Y@`s{eJrzkEGz zmGPHqmcf@o6dXneLzd8~RBG8O=kGHiS|xcl6nO8uYs?ELpdu%b&Msxdz;+_l9<5kH z7&1C3r6gk6ME<4Z_uAz~*1n(u8r=FBi8N{<_b%(%;B&(2UNyPSSgy#$=cHs~ObfU1 zbTQG^<@rE}R+VS82)vaCb4uYBta^0P3P)d_Z#42-GBV-mHR~*22pT_GqY>6tKOb`V zVAAyr=I({{tlnKfyLz2-{b1SW%JwECl;{?X+3u+|RiM-#37?Dds9(qerjQUB-C42w z)9GOWj;caKCtQpk|AM(dHV%Z5{8g=`ugvF7eS05eab?hwe2(x|{^*TTU>JD79*Pe^ zlV>0i7wyb z=wAVGwULo<=BXty=g@=z0)|z5y5UaoatOQOa8gPEwN+sIOaP)04N%e-Md%^{2C)6i z3^u?~iKGa+YiF?PiQX<6v`wHS<&1>tiu|e@3v~xP9C9DJHRrn)fEEr++!SU=6&GX4 zzqw@7OhwRZXH1t*;SSO{Aj%}>#a@z*t|GZyR)|dz%(gKr=~fZge{|;pF2)&Uq7Q%x z)_z0LanW!fJkhi{;}gLNO>F2YS6eP9#IyRD_E;{v)1Zityo84Kv`=9n3knV%ZE0D3 zxKHusjcIB3tKMVoYtm^B@^<{pI~qklXYlQhYsx--tqbxDYu0qHbZK9djB-0fmBSy6 zr>qL>4cRh@b|-!yzNY@;mkkjNmZ^6l)G}(be3I=*RnmG4bi{y&F>-2iDcajjTH-F& zP#Q={mC{~X6*f20J>6%&2QnrWh$U3^R9~pHyycBP6VGTr+BHRYL86&)2F4yGo7mW! zU>%9~Ow0Gm3*BPy?JGA_{*K!zffyKn_CL1nm%s#SApQZaS69O*C;MTY3KGDkk^i)N zX7i2m@;CW)sWW*7p!iMIA1=C;Z5g!m&M@m+O|i>)D`%v5)kjU9fk}$GM1){rnS$N3 zmTo`HvH1q6&J9_o$EA-Y{G8p@WWMc+{ZO$M{z z9$14g5={bRCG%3nANb}B)%R$?$jf?X%c4h_tTN!?h&4qGB(B{-^+T77r~&}eA&pYO!h{KO4gaU<~mnJx&vJEPCv|lc;`V4MTlcf5s^hT_A>Kh5^ZQR1h zFlr5m&_!Xg)RLvDJwQs~-;5(5O$ZO7DA|wQmy=a(jl)`&Pe4}K2``n!YhBvgr6xa= z${`k-f-96-odasKiz=qDx1k`p6k}wmpBXwAehR5ja@-bZW=CNN>+_8=#j+Grd|b7+ zJF0>8=ND{z38~^}-ZTMgU-}aXED`K&VG=A*fKV?e#3sCTu!cyLeNcApSa}MEzND8h zSj*i`Q%*&!b||P{QiUhxt-+K>8R#XsEfiA??3uB@QMXoi!Fjdh!rQoS$` z2Hw3zc|YisBnbsgW}&}yG&NW(4CV)GBW)N#x|!=%dK<;NlQMJ-%BTTKWPybrGd}-OxgY)<9?&airGKh zrxaRb2n0Cs5k}Z)iKCu7J@nxGnmY7do2U{upKe~C*nI{zOu^#O&;IvA5Q3C+qxhM5 zs1Im;_$*wU8=`h+1R{$Vw32SzqPAeb`+oZfE3+26==2_p3&=H?K!%2c{uKUy+r#m;V)6H;RvMM)4k{wi4ETDreh3==!tK6 zGnm(SI9R9mFPJy`1}|?yU+AJxpyu>gD5DYG5Dy&m8EC0cYk=_JO*{hSPNC00mqR#G ziHC4i1E45aztyUIgasBESKY$tWU2NKpGM)|&`21hw`{3b3WhBNWz`>hi%(l(;BRDJ zl!ND39*K51Bl1=f>9|<5v^+m|AwjcKd{Mqnzhx(EJ{h3yqn(6@dP=s52C{M#@p(w@ zzn^g7uli)Euv=D(_~*1jW=f9%YuD0_sU%~(L8=()?nj#l=wA+I0GM!wnHU@1#abti zE0zSqYsvZGjnN@pJWC?=1gi!;-6YFhC>rB>R#|$^C4Si1;q2vE;hQBqaIE^?tV>9h zvd{Xj;(^I2_ebkDxjx*a0HkH24Z@R`^>8??^Vc-;Ep0uM3&%8au<2B?#tSW#*i~7v|G@QeNUQ(9$T6r03=J6fcU~M7lK8uPG5z)d3=^1| zzTrT?jSzlwkKqGWBcWOd0nu%x_FO4~a#9F=_|0u532Msi#1;7d^f^XIDWkMUGOEjd zKO-GQ#;aPwt16p%3}90|Qk}PZN>{}k4hiZsT_;pf9fD%#tmH~q?D(TDf4;O`nc{PT zjU%JFIb=j(Uz=%-v7jtl)PQJ{H3Z}swC-?D;@INbD~pWglXA%CSQ;mE3T{CHMnMlA z!*5V5k_1@Sv6>=PmzsV=zE5TZwJjjXR@H*HyQ8xcJ+K*vh+a?S!Hw$L?Sln!6~PSh zP0_o$L|zPn9r1YyUvaiTyOzgts2BtJSnwe5+0ZpybM*RT6rcqX74q?oi-E_Og_2lY zF%U)99ceNG$4*Iuf24CNych9DYiRA<5;{lzgluM?kx)I3dM0SZtcYsH`$Kz2UWgDa zxZegeUKp7otxOGu!P{B&$uL6cqPz5xA&s=#{9yt~TQ?~QR`E2DpUeYz#ZJk_aC{$M z0iTG(c~e`p8ZzNDD*CAcWe04w?f}K#>YoNb6q>SZgW?~?C#f1C5*AqXlVUsQxe&=C z@&zQ6=~i1Ps0uuZ^kFV2NG!pYfrvxq6kHY|$Q zOX8VOLUKW%#TXUo1ZPNOna7b#73*C>%2REbFhg>sd?K#S?m6}j-vZT{G+VjI`}!w} zU-yqD+`Li)n&xw9uDH)`@0okZBspAb(h7B0Di+E{Mjn{9Ha{W)n)Pcr6W|Nq8F>+> zn{<2STDnmNXVUnwj_KX`{D1)h!dw1rKpv{@?z^`y7ha)UGy`U!SNDgPXL}EU+9Up% zldq6LQf7x_VnB;qG!Tqb7n=q|uiygmn8S99NqKM?sRe#ww1tUb%-z7MQFWau!KEwD zODC27`WWg>>7&i!j!NVTL7MN=kfwY>nOImfG=pTGwipc(b54ZC&65Q znc*LQe{?A8a-uhW>fPybU_W3tr*E2iy-z;OHJR`hzLW>-r8auR9fZ7vIg-cYAuFo) z+>&|!x(WX)`q^J(Hh0tikm1*7JEP_)AyjVo63kGFH3I#J-(8@C<(K~7;dA>s7uL3I6UjH4b@0WVTWg{GlrP8eGI%AUbsB z`*^A-hvosjCFQv&^ZjNk?vQ;>v?XSNw<(;zWIw+(DCZH>C6xyZm@;RdL;}4E-@>GO z8pI`Wh!>d!?u9*p|00mTdlg!E+UXR&A;tr@l&{hLI|*>T1RjCnAE$9(j(>|cYaCaB zDYtxyzf3mb+Myodl~z>-;RR?6Z==3p>duPZ+~2ZRmDFJmir&Ind-%J9RsLwGilP)n zfLH`?IKPI+6M=F0X?NfDiTCzPAHfp~Krr~J|Nl*XNCqF}KfB*j*~0&cKajj@R+kng z(Eta0_${@FdMkJ*(vQ)GbWgQt-w*hP;m1S(vxA7o=(?9nX!f;NmCyaw%+&ptp0R&m zsCH0J|M!{W;7sp@fTV%ox`hY4H=&!1&C z6EsF@Y=NW|H^O6nGDzS>i29IpJO}CySXh$vv-@^rzGdXl)rBX>;f@=F9n!2@N_9MF>C2_c*Wwvfz3;M8-!xwk_P&#Q3tENyNn8YbT%l+M>@E7VRIK zd)23@Yol? z&q$0cSs)}^@I~K`bc~5SFse_&h1lBTv9CP{dP(sjnO077+we`CpMY`zW@6uUKKwY0 z0@DbV5YK@%L)4K{+(f%fC`4|z_uAHFp@iqvYq#fT`K22Fb4x>rUxq^@`9vYy{;$OD z-jqabVhKTvww(5Kj0+;dGx68+{Yic|g(d_i9(B8!e#^jD@ci{u%n{|vr1w^wPgWf{ z#=Y((7MhwUX^9aS^(9L-FrL8#x^f_hB85A+Vuub;8|O7r3>>{J0@sY9WroA4O_IQ* zInfq~<4N;Ax+S#@oAdw|nrYSmj#p!hZim6{@4Gx;HE4vTlVhT`dh1BS9Lq|ozvxxK zm}hvjNVk8WV2#@d^jt9}bM(w2G}H6>@{a}t?zT~ZZN#$7+yrX_r|>xI%W7t-l3%0` znVOA_B-#Ic<~tVu`RCkWZ!CbmedR$GiGnc|wzjqs{f$Sw|poW9VV(bQgFhL-7lyTq$E5$-1>0z12AyH#lD45Qpwrm-1 zCcG6XZ6y+u=ns-=GD4pIPVUJr$Ni!uul97?T>Rkh4eN6?Nnz|DX*B&r-E2~*_wQ>W zxR}=lX9s+Cypn>aX>{SIw*uo@qsb1d32MnkT7M74$ZmzUkSvRmj+W09M3QXNP|wt3 z0W_6C^uc?&tu_=c=tg>&Hk2w#E}ZZXp^fyW0GS>geuSS~`iV9a72c%=zBUq2Z|DWTYx0pO$SPy;B&t4TY`-=MS?YC%;Vswq&F6 zAV0Ojtk)?5?8y9>)p>_MSuu{0C@?_Tx9uUAVCNRg1(>0Q(op%?la_emkyh7n8qp-& z8LgoH!-|W`@bB{64QQa~L&FM0GF`(u!DZ|Sj5&&=?O?>qV%CR`t_x`!=K9yw8iu9- zN(>%nIOeDGv|BB&h>kjwcu?hB`)sAh9yq#yy_criL3!~#A9-1EL@6m_p*?U8q=CeF z4+U55$tfRm5xV0^MEd|#rcU>E8phUbb#}>dB-iO)xk=oYjNUkwZo#QZ&x*2oj?hyO zD!F^81Z6DPTY+joq~(|AVU%~i&i1dcST_`k{d-c+$_%3XeF0|iekJOjf5JbyKfV?w z@|o52Vchz2lCMT7=OvxA0Q|u7k(&h^x1|VE0q~u8@1mj4i5u7cUz4Gtirp~e>yEQG zmm{xYR$V%Un+~K66iE9r^)0wMXDI3qwDENQT;7crV15fvbExuTM##`%U^-XJd?iSq zBZ+!wwTd_^Nwelo#g%s)6!-RQZ+A^eVb6c$)2O^`)RyoEH@4q%71-1J^}m-`Rr-TI z6eonYi1y7l1P2ruDo1Nd80=hQ+$LTUa;P}KhB)2G0E!N%B%UUbHCtaXljYnfNO&2L ziVItVTq{*#L4YT#D-4^4c@u5AFR-8sD&%Su>UBPE;P>M$C5HOPh#!KZ?O!OB>MbcG zz+mGSrEJok${Nv(lFhjtJ**=2^*t&6OtY({I+IH#dkf*;r>T&6I;)qSf6v4~6zx8UK=gDXh5|6Bq*TN10g`NFRns=lF#=o(_RrheyYd&|Dp88PXGPiZ$3X z^pDo}4-V+bN@bA0Wf^HHQ8UpaLrfXD^n8c!n+Z^g_FALZsTVz&gfThcLV z8NS>P=2m)@-wwtDG`9Rww(uzb51l|_zY=3vH=Nm26<(!egMTk_-wL%)cgXXi1!UC_ zTV@#65p(U(Gd9kK((>)F{t&cfMiq7N6*Um#$lz+tj4Mu( znhD(ku?Tw$Ma;K@yR8h_Be|4_#02S4m=@4Qvcpn6r&bi|P ztH=~KHNdCbSVhrZE9-IVM5K49Zfv{OG?_p}I@)!MEK&&qB?pz!U zp$R}K8ImPK^dDIf=mHtPBgSbHfHDGq#k0K71kjE6$|it%wnhDq(2fZ-tePPwvQ9Eo zSvI47Uc`V58V9gjXq9nN%$Xg2PJ5!MyzsDDVN~l}x$zG&kBBCLn+t6jw-&AelD$Oag*}HQtDJm3aap z{P}q*KdH=0a@7LzdBOU?$RKYIl!6HOCZXQE3o*%!?$kJ{Gu^G%Op=XP?{;4CuQ?HC z3s`F1=-EzDS@)^5kLSVZZAP3x`aEwe1U0zHX4byEK+09&LU^P03`^60bf>{hnQySd zbL+*Fq7Oc=JOIs1yMYrGTR??C(2mNqhAzO+^hTu#yM;KP*LfKoVgc)T$AjdQ=-!Y-NLQ^UMV(u82l@YoKZaI{su1LJgm z=vwBY$s)QH7RU@H3w||!Lgs-50Jw7l7s;IJP?c)WV5JT;FaXhjCgz}N>S5nOwooDH zqgbaeOS1)DDJ?_x^m)8`#iUkO@k)_V^2>&J9fF1qHIu4=?DIm0IA%NkS=)SBtw@dp zRy1M`(1l<#m`P1vkTABAFe8QtQF>uIGcit_r2pof*ko4i?Z%{k4#Kb#RrL}mA8nhx ztqR7#(KRhfkZFIeUQEl7Tx}NlYPyt`dKpCv$frfH(e|epbM`f|bA4r2yHG{lbLEl* z+pF8~WS4}f>Ed|QH2GA3qDp)Bib{K`8<4Wa{-V^LyeYe*_>(o!(xYPqrZ0+Cz7$2z z@=(f#LfVvPER|J%w`Awrx(~_L8J#KbQYqzDr`>Xxc&r#Gt`ko|CAO`uSvoFK!iP@O z>#QpGff7NwgDl6BBUID0C&*dyJAGX!Pv$yhkQe$*;@cZg@*DJ&~2xm?o}eB5bTs$~jX64P+>-eyWT-UV3ZV8}M=?Re4HB8OI-A z8q4noqT0jZbP(-keizJ_`_(-k{PmO$s|fw+^v`M)_*m^Z7WZBb3M% zo!{Mu^;LGBBv-PKK0x{INQRpvlS&m4>@UR~ghd`+o zUZjT5kRZz5cCawtBuZIsn?2wE)6ys9UN$2>E?iRduv81xU$}(%GKTJmXvX|DUj>~m z+3jS#ibFF{eTqV|01h!}5 z;MVV^DOrB7gHFe~7_fIe0`_BpQXj4h_GB(73}c__`k2J(x{oJC7$^p12QjF8zR4a< zZ||aiv{2Wfm!Ncg$t2V{=Em>YU7Zvr+fd{>4{RSMYi;)ZYb^g&RoP-7iErT|lCRY=u((1OiXX)X$`?Nry-Ak?*2{bdh>D};~a7UI^L z296@Pj_M{1vqtxzXH`C_Qv7cpn!Re)=ehTk!VR-5y|fe&?fR zjtHa%XK@J#r#qVW;GB!_P*abvVi)0maa-Gau5Yw@*E*A1fNM`LK5f$3R%gl!|Jxeo z2W4tjpDVnMy~X}a#E9x)t=$T>M6Rr(J4<}!JK5W|os}<77sV>q%zfqt1-eli?fz!i zx?;)V(V}ITD7a32>QP)l2M`HvVr55Wirb3a4cz>iVY+;{V`Ums}~n&0y+7b zobrPT_XZ5>U2X?g&4dyA-i9rIkfVd|XT=uCAqeyb`esRV*Dz0aPBU{~uEB)HDr9>h%h%K5GyRITHU$maqPQo#(X$`XgT3 zc9FFzL*t1IoMzOb_*O$yO5H+>K4YgD!fEa{sOyIFFQs@>uFo;&BH-!Gqk9eGx8+WTTbwIi zPGg3@VDY@AA4VYc%mp%kPp7*pRnz;&rP1k)t}CJE@9_H+tqnE1Wa9eW?6Y4L5%dcN z*4Bo7NWm#zPkYMEq)~2^s!MaVLAv58<{t}Ey9;@gANURNY14$6=YNpES9h~0cgNcj2dh93k=(bohj?fx1!RtIAvzy&8ufsG{o%X+ z1J%7Il$X&f1rq`^Hcr)~l zzS6JZe+f5t`l>v^o)opa#Wvb~c(1v~H{zCCQvdoETZ&I{tk4E~Q!f4g9@~fad@>%` z!)Up0dQwLcpK@!hVh{9Qi~4`#V{g{vHqz!Va$EUrdV(Vw5vi4b2U@-1)C0tx;#_1i zCar~fjdX0ORq3u@<9dnS^e@h>&Q~RRDfi(|f8YJ?u%$*aus&}o+)|?({rdp!HIpuO zNbdu2y8&<-GE7^<7M91KY5UV;^EB(%w7C3Rx2W)>?S;mrFA8}}4_bYAUp~vz41914 z>;27}GBcJ24~%=+5#aeBFR6)rGR#})bl(IY0$>xtEWM&8|C5@`502!DDQQPC&k41h zf3F11tm%7t{(YXWoHmh?88s~NKe^^F%Yme2TDZQ|kGYAO5k@M>l&2P&rv>x#!1oK)8I}?#oGignp8Hq2A z!pZ0l?{Q#WBpS($IK6PzeU%IGnBjD+e;y7beMypzresx-LQ+I2v?5%doxt65d2%XC z7N3{qXKe)sWP9Bbhernx0mG@LNcrTbd33m1b#_d&@Tyv>T(zWX0)9S zUPwL#fGMk|{BUy6L82sqffhlH-Lnp{ zNr2i@9bxu5BIx|p+?7zwaM8_uttOQ4jHIqW&T;0-&MRE40e9r(yk7|l(B5`y$x99! z-jIU!1|@7r!bIN7ARr^B zXFkj#7;<;55RXq&>7_3f1HdW=S>ib z7iv!*3wjbqwcTdF z1@4>!*|peWL%}U7_I{Wj*2CaFaNaHG`CrzG6Hu`m*R|N`Xk=Y!x)v98G(OaRI@HN> zP)A!ZBh|!4v74Ym`b{OKf3hM-=(j4(TXBeLp^eS2et;Fg3g(1;j1|BV zGKN!DFofFPlAGclH9p}0rLv0xQQT@75)?A1df@a(uxPx&NpMu6sI9vu+cQp{5@Y*D z>oYD<87WlOU6b`8f0u;Gy*e3Xz8ZnD$G~AV8%G5innIcbhfLA7F_H-ft2hI_o+-8If) zWiRj=SN5$)`QpGQorz?kR#0uKI8v(_qCan>N+o-{`e1^Yqe-BnuR|v>KzD929x_cW1~UOS30L{L%`f1j_sHH*B*ejD|_opJX3WI;eg zN)Zvrh@|Z?w7Avrvaku~Ve9v9wkW+xq6#v08UaOjb~>MVbh}gr%#1R)qlkn#=!j|; z77lB}(X?|V;z+!z8b?^L$+L7SvlvG>vC2@P2;s&dWS(cDmy-ImvG03 zoXt3%Gw$r8wD%5iwK#~usxn%QC-5teGu9q$FK7ZYc(z5(O&H<}_~wXs^Y;lXu7#<^ zf4!C6m^%ojdvze&#-}9#X#gWn*n1D!>V6Nd@iW1nFuwD}FP8L9=!hbgxm}}` z6SFCby-;}jV;Q(W&qiO7nUcCYf}7>>f0U>a96Z94N@*0@?wlv*11ZmhghzH!X~V3A z$GAmV5yZeF&Jzc6Ka{L)T;voIoIM7zWw^CxjXbA9YPOzzK1NhLb_$nThYwI_#S4xQ&9s z6xY)R;dJJMHMfyeJ`j4%ZG!9wFb6_!BFSh|H8LlaE2&J&=BKKe|`GHyMJFLl~XL#dDLZS z{RwBQ17_mzYZeq8PXeM-^y8VYt@)T1HeV2>14?yR5aqHi7lguo3ZDgY1iS?K<@MZY zHTtWT(Of_Y>$&QB+(o_}e`jWx#4hxWTG1jFn~yTL6g=uLZTcoVj7b4IL;9j^^yABW z0B?7CL!kxa^@HPS7h>VVc(KWP3&|=r&h6pfg)P(+*K9l7?I1Z1<pxU6ZXQMzw13#NrR3)D_VvNe2z1?6w-k0YcoaNfe9IL#!x3f9=deQt3j;i_qjv zAuC6r*=8zEkM7}s(qs;r7NJ89{7*Su1HPRHkd6-eCI+*0wvS~KXYTqEdxWk;V>E-| zmV-GptdxV8siUrgoL}L#`4tDH(wJV$9C{`3+&X{Ap;sk`UVW?-J!D!~J=iC+0A3fi z3@v0^TT~)wF}ptZe^$==GRvNPpk#4n?JQzWPYD2PSE7rpcBZJYjx|pogrH>_qN7L} zgf znWMlp3WsBfH@q2ey2u4JK-)|5-VQoQWF>=L>&qo2m2!E~WmyD31^K~O>Gd}sr< z_GE?eO&2eZr2_XF+s{3jMk>@5<ilD;8+1MWYPJ$usZ}AG0 zPN6Z|Nr0LUlcd2dmo$iVRfJe1bEO=T73QU|2Ot(3f2MTFY&nYv5Oy+SkFkV7%(Avl zIE%cUaOfu!2lrBoC?L|$HdUzclbzLON`@aFX4!I9GuuW{c)sEo55IOpuWe@IOPz11 zGA?NGf8K^>rnSIy&088zMNLU51wAqSr4CK? zwJNPUCJvk@fIg61h5y|cnpF>^z*FXxNM(l ze_M3O)6G^!y=cRCmtUk=o4!gkj(KfA^Ez7_P9E&BhR8cm4AZ=8DhaT*aNerMQw}w* z5t(Oor}&^QV}0kuev-HDVvDxl+aQ^}+bPvJ%BfQI?vM=b+Ei5U#yd-b9TI&oZ6dT? znYP|tGHuJ~)0A#^W}=ot*?GpUtAYoGx`4-vh!>+r zH1;+}8EqQ_gD{Axoy*%pg#5Z2e;JfUpf|Eej)!SJO^`MO#?ZXO4M-6rzE0ynw$MV4 zTNMlct0OhdzY#*?wGA-UHy{l&V#WZ)v~juxu}(KCS~~Lx1aj)EYW$=ok1Ixxnn^x? z`svG;@7L##Dg+GfSleuS{6ONN1<^HHZzU*;$K2viUW2%NQ)AAVr0wr#entpuwQDP%l+tM;xrDmPy8O0{n_B06|u6o*evayLk6)WxNX~bPghIE^H6mf2frb3!@XSS`UpX zw`N;_3RI%6YE@UhRN!9sr+7!Mg8O-X!od|8;cs$9f4>^9Oac(KNfWGoV z(y+l%@HSqz(YjsJe&Cq1WE9>q5aVQtfn9VhY`nGluuFNNv%9{+zB)Om(^4qqRKxF?o9mnD)wXW!eKn2= z1V9~OE?tKZvZUQ{8^fBRWL5OwR=M%oT2(GV7_H#Kbmfclf5K}tu9)Ydy#_R^f%Cfc zHOENHIKFCoz5<2?5>y$}x7!<|7MLWzQrl_`hlQgI9g71(xc>4292QP8;o&g1jq&Pv zs0SQr?E8}NjQDCok9%$1GUIhV3i?Bnm11?njG$G@7qVts-@oU@` zNEu4_#4S#72dboRq76#%8Gw@ha2df@j2OolLM8>m$@bpHG|pQ!N&<|NW7uvo!#K)$ z2(At5&o)b-YSPV_n)uv`?1iuNxe4VMNZk#((@feh@Z>n4&k?pIcCYLSEG zv{ob)e>+H+DiS!{_zmizTZc9mv@0gG>PfcIEm9zuvWKk=35t3?*^cwF$@>)^qjKq9 z315IZ1We;jxIQJly`!hOnuu4Q^@#<*H50r@ozX$vUKSH5!N-#%x!fsF4v+ajg%hFJ ztDV~=Cn())4YF^y_ks#KDz2UNGkCdC}B39 z;7OB>n^oa*_&|Y;pEce6Kd?{7y8K|4#z*}JxpGHAf4w@~I{xa4HM1zH-}g$EzP4rv z((}W$YFxfft|M=4f9u9hN(7Y4B|5tj52Ug!^#}r@z#g>C_J1NFmwA+{iOG~!PxQBA zf9g$$pX~J8T(a7Kyz(7VG*%mNh)uQ8*YSQib8kuu>+NsQEG^mLU5QV~z^eDzmDI2{ zLvN!akas=z?ed=guvQU*D!b%Bkb1?Q*d}|xS*~eqT!ds>`{QAjLl)ccny7x})7V|0 zVLb}Yjw^OCJ%_f16HnGLcL`l6uj1cRYv@QfAnuXz=nso@&Z)NMr2g%NTnVKNEEu0)=;*AVUAZRL8#+4mNEZ7&k+REm(eQ)69P0im%s!CC-7dm?Jh~1ROyp{A4wD?>M=8Wu#3a(&PXCf@l9&w z+rQuB+h0G)>Hq!br$3*{zC{roIP>=NU!PQZA>Y(n^a7N5^WF;3>CJ!M{(h74yMO=Z z&%d?#G+4>Bf^qX`t)%ouO7&ezbC=S8rq3p%=O86~fB$N|PNUTQ{i}{4eX?ncd!+wq zo|E|5l(+tdPqnA9F0J8WADdz5dtRGHn6lFQSIA%BiC`Vja&WJcABYq@X<{CimxKE| zjh`7^yOPoFfZ5bDooqRNK4I)E@S4g~vr|AJGjd~+gt9qcfFB}!qf zO;du%Z}JRTXY7wKVI{PJ`Bco744GPaI|e#!^A^nmiO{#{X;dWAgj;{oS5CBtHvUn_ zvG9x20(>OQGTcT$Se3?R<0;2&;$=7j&*F@aXX=>g5p-%n`{ItnvQ z$+QT={(}`#r_(o9=meR>j&lli>fssJbXU@mNpUL?tyP|@yh;NXwXj+f z4OAA;jCaB;0ng`epIwNE@2l{9)!rhyS}}AJsm_!wK~DBfY0n`eV?kxn(TqFNbQ0UyS0*+&v+l2AmTBdEA*fJ{yPB9+C zc}YPkB?pE;C1o2B2>DwAkq7{hp3cU+q5)loNv69X5em%P1g19H2vSnbJCH=ls?(c)62b3;XrX&qrK@G83n<3RTr)jyD>Ibln~`|L5_U(dvuK?PidIHMxlk|jqv(Ei)w zSS0|OGU&=9Hw!D-mCASZ3E9PgpC>-%4nwn_=pr;X;Pj+ba^IcRGk(99+J*+6e>cLu zc@I11>`WvK7@@UY4&XP7go#%8<(L^y?sx)n=ml3VBA2n`L}#5rvWsuX!E^U&Pa96z!e*DR!mpYbzY*K)a&&!E zKNR^JJSkjrh+PoMD@F&AlDkAy-QG&p=Ed$#GyONd$1T4clN~v^VRCYZf4IuzL=bF( z8*4#W)m=7d;gn%nuNHhiFn}V?JILw05L6|_DqK(tlS{h`9HnEHb7lR?jA~(aNj7tv zu*ker=qeYjQl1#tQecSlj@EjMf6&^QA}zccoD=0CN;+0#-t!8WC=@4 z_)0lU98U#{rH)kIF8N2)LChcFo*vK4YU9TYa5YJF2C1k5r8okz6H+($uaX@{H@CoW z)mm_P40|RY(YPs=f2=cE&K9_@Y9=pt3hb+vJDoF*i**mTxuh^j&DbghcFA#L|@ zbFchu_T*V1teJX(d@TJlMOQEH&lNzYHJ zAH6$V>4f9K5(1qo)Q%NCdSK+6wcJPGv*Xc=RO5_H0RMwh*JBBpyZh)(vU#u^5YM zF^_dolDHFF-6u-ate7#bO0GU^>lDu9RNX{A?azxFUWsHN8C-7{;VnpH0_Ft4i`%Ym2BYxeG1A=Y(pZ+Rpy$e1GcbXi6J8o8@n|(K z9CaFO)@Y-Y@*?YN@~`wYMMG(q%F?99T1K38f6z242cDH0n0P1-UkXD_Y9p?5REH(Y zF}~r2$zC{Z9Z5sW&g$L5lAAYomMEvh(>4Oq7DVu!EsqKYN^LvA>c*dAu!d*DugM6w6411-^^v45*2ktUIde@tA=3l%n?NgEd^8e-8rL(chd`76c5VayJLlr zERN+x=hrxRaEX;UF+J81>Z0364_b*>GN!PxUk$5*EZK zwa%!Em^$8e$GY|4K9O6Qo#(9PMnHsr>O^sMx8?`%?Rl{{5m-nyr=m2-5i~u@rQvKG zTIvzxobmzrLSl)HdrVFEm~y)JGH?|%LZ74rxMmNBnth@nX^Y(v%kyJtOQD+bk6~89WxH`U z3s|?6ywO?CFn9^u@cSFw*fktkf5AHT=D@xW-j-CKu;VGjf$q=3HX#D(tYz%ku8F@2 z%Jl}roK`3sUOI%y!gB3;lz@OIud}fV`vi$jl}4>ema${m+{bK#nf;*!CNE&%E|yy1 zo%7qN2Xqww5y_nwDm0Skrj&ke?m(oclT0F~+mh2=^cWgpqF>+@ep5qQuf+l7ST43$$B$OM zdImWEKJy}{C-qGqhEuFz<6JE4 zaLelgpXfw1ex5}7jf292uNpnRR;ZS3)PU@K&7@gFy?q$x>lCxtsc(r#{i8Ddbm2ZLx7p{vex%U)40jZEYG*|$gCx3Hq za*PW*45e~uSj{rbe|LY}+$q)~>oW=13A9#1_r9ldBl@xvmEr}XdNb9xvEaXJKYKMI zaZ-TwGlX_4%MKR$zK1(&YMj+NgDmyY7LClRPF;`JT8J%bmTq}EKNndnynLsp03EI} zST&cXtzt|la?e@%GtuKqaqs6=VpF41C~ zy{(BKDk$QdlV$=Ma+D{;w=Fjy$59BvUN{w{5yV;Qr6`|{eqW#>d|&B4xABv^Vq!SC z^md5QR{ zJjqe=u-UdF^=E8ywfw94Zye2UK7ps-521EDd~#8Ye_yT*1a`gB2X4UXa>u=5r~a)m zrPE>BfxfsIm>kjI{XDDJ=fmwh(}W||ZiBG=5XISVxzw${q-)z+bl3Tp$Y!h)Uiw3_ z?Va(Y%Y}-=q~twHd8&Af*FxHb$1bk38y|&|dY*+12XVS>RfT&iygG#({g&?#0Xlcq zN#wTue@O1)j>9>#CO;q4jMD|tAy-sn9A;fp9l)off*IBY)j>NE!a}uvtI=KfA~<3! zh0G1+^^T>{gQj72d@kC!);ZWu;3ySR&xfZ%oV#cZWItMR#>6h!$d8fJ1TA!8-f7l} z&@N@Q#>b$9A1^V_{R$TbL2BXSt3O^fjUEhwe+!!`LcOl==vTU0+4afi;3bWC>agzsIDC+>R^XLg861RZ%*x23Qm>^kzJUU-DlgpVkB(Xz_YSx*WeE{QXIa&qbB zf8xFZHjX4Ui2OP~-76^pk@Q?)MLqqTS8LdbYu>gX(C?hm zZ;0vjoK~`Ie^o3dg>LxC4Yj{bSMk+vEuE=JmB3|pe}sCWB~=I_#A(izjvU&N=f>t{ ztqx;}0##zA5J z@VD=mtpoxf0NIf`1reD$9 zub1LS35A4Qy8Rn#e@Q?Mrkx7UIW08vFk(^ag3*FW?mINsmugZa%N-War} z3j1y()wJXu_das*PduB#D-YRqlwoL8l!d`+ID;PUeZV@v%%9G9^{neLh`%go#ZSqIB-I|j&az77GE+{zG^Z^Hx*k?|e1b;{n0v`O4sUzo z$0;N^M>Y5zv#zxXvEdBcAHvYI$#0wm>9F_Kf0r#`C}%6blE5%OwporR!|gj{v%^}(C$V!ahf_!SM9bcAHi1fBQIOKp!PVW?DH;`|H0FLb;X_*Nzsr$&L@}atH zE?7v)v#IgBhIAcy8(V3spH`!la8Bx6R4!bQ)VkKVIMB;G{BV$y8T65yZi?=-v)xk5 zf3UnAfh(BQ)HoauGA0sESFYOqJ*pwlm`cyNj!m@V=hT!`<9ECsO{lX^MJg$u`gTA1 zt-9KOm*(B*V{68$w4V}39YRKqCI`gix{ve?-*_bR)H&qHI--XP$mwPtO`Be&dTPC= zmUfzyUDdk(F>VV27-kcyAIQil`g{N&Iyg9oyM8Y%G_HHr?z8egu;Qb$xsD}+xEU>`GKnfNh7v-p^y zZ4{KMaXwFk+2;h;9X<4<4trYV!GbJJrLn@uRrlftggWV~&$8c-@AR2PE*n zKM(xbm(eQ)69Y6fGncSM0VkL6r3NAaIhVoa3l)FGS>JCQH4uK!U*Si1z-Q0c9vh)b zZ6SaJQq}YUsPb?mOM7a#3zrKj{Pld}J*RhJ(>UZ*9@=y;P@!TdS8O)S66;n)(`iPw=EiF=^GJGbA=>4Eh#E47;>b0glNd8 zx`Msf)u%9+KENs)iaF{Y#gLGmBQnfcPmOqDp~5*gN2$ z0Q-9I2oLz8FucXs?Z`tUL!9xjF*8@yb(K{_0zP?tQ`oSm-9pk;bz=&KOEn5k7hI`_ zO$HvTD}j?s!65`*j?mx3vDmnZLmVX>*u(qS1#&a)$Y`&uL7|FdZ=$Qhax&42ssw)- zk<^s|myvVU4e&J9xD+ulmAXSVF{>+s6cbCm2d$Gwtayk^9&dTvMwCHX(Qw0Y0m6#C zo(d*NocO5vHic>j95N+@t&h+(Np%-=O_Fr0Tnu*CcM(bAs!AEr>Wbp9hxi&RxI`%H zZpb1b7VH7H2xYY}B2%~qRw-CPe|Ue-8_~eWim=iYiSVsN&5`IJIck!?T*wX0k_a`B zB~e$9ES`_P`pV3{Hm@~I1=;-4%zpa$7mX3?p%5~_I;8OO`r^WznkP^0!ZTTq@ax7m z`JSyq>~_n4ARe)1Jr3Qg41p4Lo z;+uRbmXQP9@_X@3zKd2+g}deV;_EAA`-V-?!cPCOyyj* z*BW4r8P-cfytNN^oSCYxT38`#`iP}R^QWkF>DglcP zTa>Zowg;MU@$EhAMKtR2w{DZE*S~J+^$&~XJ2QK>TAvT=*Q%O7 zoqad^e)jye>fuiHIA?!q2oNMxASE-wI_18FQB9T7L|fp!)7eu~Bjd!(zFoaqX*_;5 z{Bb?sELKbV)cViWvU?VMgf4=<4mOvZCBzE3V7ZP7hvY zump%Mv;wh3mS&_O_$Jtjd|Jyu2i+4BfvrP~fH7h4X}aB~3m<<_7jnt!T*Wb4C7}fN z7T`4&XG6MIl|#CSI3qw%ic+vTy-|!-**b#75{lRT0kh|%T4{BhyQ#E!Oo~iOP$wzI zK0H>qu(!g>cXYy3=xQ^~{g7R)N(U4E+Y}{sxCcv*Ykyd;n4Z%%!(Q^kF@YTJlPsih*YvoWEiV8j!e zt`KL7&0zmrY~~k>cV8@EpY`SHqSmj+)UI2KQ2_ab4}*WlFe|xI^@6kug!H5E5zWrl ze_d`?!{r*PeMye|41>QrplVt^8Q$fH%C0Oeqs*e)a3Xl!e?+zA{O`s3-P`$c_2*nQ zTP%NDt$#nX>BcSylX-9TBTm3T?Xu>bt9st8-}&O|a#&vt=NH5In_+!OcRDSDBj=B# zr6pTJ$JT$pd>40_bSKS3;=kKcDi3N)d+=?aiDb13cEV!-x1er#03DF&VP^_X1$jyI ziAwKYf!!~?ch=XPl6tGy?iX^xS+dy@29Ms8Kzp>Law&+MA{@G<#3f6Zm8380=F%Q3=V%8(>eHvet|(B`X37-X0Xc8Qu0tK zA=Z)P=wu0$H+%l{1@ZQHz+`ojju_s`_}SS;6hg#2ye}O*I3KbUqNBli&;~4AKeKSE z3{kal>Hn$D^*dGgpb{LKDc`Tsy~X*l6HFnSvyQs(VA3CX3KSiOs(9A~GrxGVS}!(l zf1iIEU-HAompnC(pso7U3y*>+UAocehk5#I^Awx}>?nk8xEGi)f1<9kQ`2wtj=j>q z*CF#;)Y=ZJ7{fQZ5C3#=zam@E70v+^5*WT*vt7AIbLM-l6R#(%&nsGK>!K zKIr#B%uyWr#dqSj;*nRdwRDT`#W(SS=;G2Z{-Jn~;WYir#WX$yE1};y2n8wqzU{>~ z@jlrccB<$ZT+jraZ) zKDrOqNYr=6r&NJ@@2b*soquq9}fg zl;z#eck=GHALRD?`R&6uugcy<5gj;l_x86B3crwd>MmFzb-eT53efn?m%ASyr8Mpd z0{+$@rFTyc1^_>)?|<>hbN+EMe@lPUa~BZ`KU;;rUkZeS{0+Tn4L#M5`8@~wJCUHC z9@2#LM}8?yZ8F%7i+Rao(g2D|N<(onvNn@2U=-q7|@Y^i(2ECau!_PoC7`@}Ly?^;q6VF3_irD?-?T6E@ zIxWD*va8nQNoeAotn?wT=;=Xgowm9BWuB|8f!B@hF9*T$Yc7#<+l|+aAkX!X)n4FN zA&r_o`~8(d=gdq8E_`US(f-){OpW~Z&Wtq6#-RQ=Q?x)5#lvGg2OCQsi-ay~#wr>fc@KHcJCgIV+7Up`%B9WgI;W-3gfPxY9EMnwZ9CfRY)zI-Cu9r%_#FtRI7V1I>CyOJDjlvb-7m6oMKjfyf$ z?646o&6Gr&NU8J2m`uoREK=wGQ0K>%DZkHKMl%4UKwH0szkKL(j0g{|N{Bn4!G8b0T_VSSHZY3zOEQ5IXbd{pUY? z`t$EUjwSOvR9NfBJT zVOAgZ%*)*fUd|i5km|O1qY}on^SW1VEVNJCJ)*M)5CMOnrIam{>T7AOr7-7pGtVY- zV^)dsN@9arQm%@76c5_R$7~A|m%}EcX*4KAD15&WqmNuq`lJ$8>T3hJI}e-nrWuOY zW|$mxnNy*Oi^j8g?!O-jkwP|8Q6q>HQf8}o|DQkqJlrIOuColPT@Nuu)(^Wk)i~9M zhqLBX*Peez9C#isXkq=zdZQG8Ph0?j7`4m2P*1qbU@e=aQWSkTQWDjSu30BWAqoLW{?!S?uAD3I!aKz<{PyF6a_;`^<3liq%=h=xpwsL)8UOla1F^D;rnSN; z#R>T~M$&;W4o*mdzyH6F#>xBtE#SU8qgP39vl)Lsk2lVvg^10BLjekCN>pGFZ{sOK z6v6wJH^xd11x|RY8s>nkGk){-;eSs2?SnvK|Mkm&&K_<(h~WkcU?D4u(PdI=*NG>nw?VMy|F_T$Cn7}dHX4`;qxiD9;(;~ z!g)ULOveJ65J}p|qK(F37pMrx9)UDDUtS{PZhLn!>J!80UJO?pKYXrUcPpMG=Cvil z?x*BjhwEh=O3bkN3L{2BpIo3z#>qz3LQSlNcIcW!%W0Rb#i7~8YEh$-*6zJ(kwbrz ztA_-(>ang^C7=%w4}beS;PtZA+a}$$85BJW;JAWh2{|+0vAXLg5ZsTx0NR zw-ZO=s*JEhXp&{qLbNHLI*+=gqK1EdsdobKs}_&iUR^j~!Qp;JgtS5x&vfE|(S}OT zCcFP`9AM)vI;%Oz-^L-UGQw%|jwJ!0hD9yGmh|^Aeh`GgkecE5^H3K73IZBu1VKEV z=CfR=el(zvW~o46Jc~h%7ZeBiJhm37RRg#a;ViQgLuwE=Y1iMatDJU36*G zM73Kp%G2zr_{~3|Gon3p51D@`TDdwcpFUm8ir?CISU3$Bw|R!&%rQgv)&<`#>6{IA zkJSNMJg2W5L;A=WyGOQ>L#Ilkfh6Tpqd#FmgWz9XgKAl8;9+ zp0>dV18QjLOPK+BlUx(zW7S8`P=X?(FZq6SD6X-H|b;52X`6WHZ-Pdkq$s%;fdR$ir`+&Bfb?-XpZkVmcON#E}UD*LQS4f7(Y z&f%z)A>|4x*V64No1(e4GJ}%Hc{!G)3Nb8W7#mt7^OFkdT+~((M%EB*VcSL0s7V;@ zuJE`%X(NN76H4FDUIjfYCo-%&NDt4yCu$w_EUNVemu-LSO(@Kji)T=+8;aPY;?BiY z%32DK!q7~%TcBg%EZ<)$Zj#VE*90=at=uM7d(okR{!#NW6FbOGPg1H-=V~!GCZ6^# zDdTn{Rh?8H2Sga8Xq1F{gh|zgkxF=Nd)!mkSnm6N5s0Ac;ALn>;oESOyP4Cb=x*(V z;k?r_e9C`ZA15)_m6b!5B`u6DRx{cH%PK$*%Mv8j=xkxhbO-3RhgU-vFG^PxU&Shm<%tvzL3F1V8_BQSPvM{F~d7ZQR#k|Lqv(C~lhV6#+pb^*q!Psb9SKC9-M9yE+iWKJkg+0 zu;~!ACeSR=Kt*KQ(QX+L{7MQ&8}!K3X&dV7<<(YP1&$l_zA|v6G8?j|_39_tBxi*W zrni5TjKr=4TyeXrdexUMb7DkpBs(lmp5|33-OU$Q4p3i0%VZk$u-~&_HWjlEQ*IF* zN9P&f{ZGa)=8h|!;>TQL|al_nZ(gpKXl%td{c6%hhQ@mFK~fDD>#@mtcL7bRO> z3XC!D4Dvd_QgM?D9R1Sq zkhG}B8yv?qcI2m0zYqi2itNUxpnwdco7K&W#OQ1i)JYx&Rboa1`i(Fy6Eh%?t8T9n zBkK#WbZ)(!!#5DMJ*exyW{#c31(@^vwOY8~cdDQ!4@5-~ieoon-J~-En`}Xq_$Ys5 z3?~#9R7r@!k}6R~XdSrkd7(<8NjXG@;zX5DmX1^j$L}jt3Fwd#Pej`2?20Zy@lL7j zhP1PCdlPX(G>4j01EfBm(`r|B2`WiRx`gV_&00l(*FxI{$B8Z>_fd1EUeqPXF{WAF zp-UF)YcyHRuyl;F$#M%(yqT)A=Lmml`=W(b$5>z^-T!(VW?3aHx_-^%TLNmx@hJMv zo))^IG%##Yr0&S3Y(+$e($H5GHFONgR`%V*MEZ1~atkpc)%HWXq@%L0`1QQAku>d| zvVy6$B`J;J9dt__E=Ju#H*g>jAx;Ep!~yT;_4Ra&MI}2eXSQN~ReOt(LE?W#E9|-L z;UX_1agER*d_x7hR_M$VaY-GUmHH{2Tur{n+oe6A1+{MF=%`3LhbYHs=Z@X6$N!6* zj^r+{7NwQiF6Bjtl!)-cnWcUK0N2h%3^^_ZiNdP}W@4a>NuK>XmW0uuLI}2`iE*+4 zy+`2qP3oW=wO*Mt3*}o@&Xj*06%_&pf%)-?Q5-K z2Fu&+Z_+Pg*+a)wo$y^bu(s&rla;qw;MWeUQ+13z5wy#)Uw4SCm5_fVPJ@MAunX0V zO2rp;8@r%FGkbPOhdH+}fH|{VH%eZ$WRC-R46K8yu|S)u)wtOhB#wkI7(PdL?lr!u z`it4c;S@UcNxrk+6VQ91%P#7bjN2bkeuM?f*D>pV)Cy8z0w>tSKO<)+`ex+|a;7&M zj9lr%qF+XZ6OwOe)%|~{C*6-2yCom62A?IEokjOiaWam(AGHVJC7h64^&P1*(Z+@W z$J>TMhS$x6Ln9ag-HX5=#z8%9Cq_%I<&4|hQ`~TSbU`{hS04?;C>Xtn4@)r0N8-6= zeO1sxK70kZ9ZSM%6aEPy}~LAv+QXYT?-19p<+`7%G+GTvz8}`&0s`qDV|)d-JHCw#@vPgD@wzuR7Fvm9M_bF*QtL7har2z4Mf!8>wQC@Sr9JC7KhYc z?MofbBnU?bE4pw-bNK`Z84)a>a(09Rsm_Q^d9!N6d9}4Sq}UpWu|wvD4p}wQ5%gTx zf4XnUa*%^%C-?a&v{FP{y1v0J8t~N1*335vagnP-IML_!`|Ut!N^r5c=VD2RQpUE^ zFWG-`bZn%}mmL_pYRl<%D$WfvZ^Iaz=frZW=c*WU#h9_QeichJJJ#7gmKVhL=tiLc zUQ*v)of!w$?AgqWVk8fWapl|O<^go{o#K=H;~x{fWYTRl4Cc!uDXY=pJySr{$&3p# ztT#@oApc`L8QKEXu4yXJ8oAGD&1lDb!9IU295SE{w+OXH_fdiS1%#Ro+N}(ie05Q! zD?#X14^4e#Bg4ihw~&X5{Cx0zVd*;`Mw1n3HhkiJ7*yrX+cSIJ(p^aRx*C{w7pBW= zkDk4!S zmp;f`rmyRUv6s4sAbF~C?*}|u%U+K*wft70ZSFDAbzB37H2A#`+;m#q;dGH)eo`(Z zNR*RJAL9DKHZ?;_bS!FGEFEkcG))-Frdx&RzJ!I2OLSoHp>FA3nhOt_C&wsOol>v7 z$1+#*o68b;s^~J#cQ4+Op>E8R-F|<@^pqV8%J9h1IWB^4?v<|IESqt3B&MUpmnKAo zBc!3{bZyIVIkt!Dwh>u1q00Rxav2^EymGV9(}Sn4a~N2VtC}cfX_b_9r>pd*`l92F zy~e1Wc;`cUlJ4u3&Gl-rB_zMC?vVa$6M6)_xK^X=x2Kdet1j(br-Ly{-9CRV;ju~s zK;7hf(DJ;$$HgRtA&+K~)OvJWYgYBJ9{Z-su0p|~>YOc47{@}dkuR@h=VKVR_o4z< z>grBE^1>PtE}U|Zo!3B+)PEOwxpZFvXm3&xcr)3a+>xrg_Cmk<#)SI6aTNMxse!MS zzb=c>B_Ky(QQIYMSf}2Vbx42z$|TCBpFBUgQZ9$y%j^}rtvZqS|HhFtVy&{wsY7ae zQgxosnyoWt-TxwzJ0{zW={8%}E3{^duZ|qfu3=gqfVR_uuEfPe7}CBTJ=0pvbq8H$ zDOFnz!gOfr^Kbrv0J?tf@N2d^3Lj81Hb2R1_hcDe{0ddwrcm85u+4wSc2vVJ=Lt|c z24$QPWUa(aQ5TCz%^^xIc>)ymNDM|g#4i*m3C`21$Lh?{F`H`#UQuW18g-YBO}q*# zhql_sq!Sp$N^o?AV8G}EPAg~UITtjGkXi{FNV+Y{nwACaWav4nFCiYGQd5FrbyQ`*P^lHaCH+!YMngYLh+tkVOMXvpia-ds?dg0 z`DK}P`+ap4&h+xsQp8p%g6hBNoI<6GLkPM#3RxWEEi&9yuHP9pz;E6@{6B*4JP4Q3 zD+Ln+H8e7putfnUm+++qA_6lsm%;7^9DmPO@UeZN$Qg1-0)>I5t$Q!f3lw!8dT-zd zSzg$N6>YGVi{yTN&rrLrHkMMlQ2@i@YG=nZo+%jpw2R zGCn6AuptgQ2!=B0AR4A>lMJV7lT9Fgg#qA_;*vA^Ee761i8>%7UR@9y5!jS$l7Fiv z!K7GCqRCD@keD3Q10|D70x)G$g0g_)Qq+b4;VM-IXIHs0Zg^HF`p;)&qTGq!=v^S^Y<6nCpC^Hyo1AHj-i4ea8rYonu5I z3Z++s^l?d*N-)8Z5)hB%M13^lJI?h{wsfB=)hny4+Qx1jHMIwx9EhIM4)yRTbbfP|x2GpARz+I_xROI=1|+@e}xqtYgl$pj;cN zpgOF>G@IcY?I(Eg)?vvs!#CPb@F7{`tr`7==FHaPvw@6uM|5OM=zrYJ@QwBpyo;9P z1)*%TAK}q*EK0xC99`39@vY`q%Ql4;@`CEs_Dq(Do8eLPy4|$Gx7tteDOjf54&P`$ z!Hcu}0`xZX2|S1mOzr56_7gml4fzF;Z?vD_QD!O}n&BJmCwLdE?oQ3{jrJqF$C@gx zd4)s&SdU$9W^NWg^ndGqxOl%@b%uA({JPw3yJ2H!clpzY?avq6<+d|BOtU!eH(R5= z&LK4jyJEFF*A12Z==dCAQn5B(U~*7Nqg_zD(b+j<3&#lpI&i1wrc0%b9d|@QNGVS! zs{H)qpvpo&d4S}hJYhmrX^JfOlASk zq$jcv034@FbT4*0vS()q>d>z)x-F8k`1Qwgvv|{e*#4EYHy_`38u*(|6SCQMo9%;& zyOGat-9!I4th$Gt9IW5{r@OvezV1H&QHesypy#OC_7+pWRI~vwDu74s-)}bk4tApT z>g`V8>Q&XZ<9{Gd1DOVC8suqE#zAz`z)u6320P@-y(v}>W^wU&wXN5`+->g7;&ne< zcf(sn@|TN$E&jdu0T;l#)VZ%TY8;r(W*4OTzqe8O25V* z+uNagxPR@}*QaE~NTb_hg&h=)PFXp$$K$NtY3lCCIlo-3`p3kEz9(tfxEqRKZA zyXw|!^d>NqcaQ7s-6=VVSl$m7$WTkL#uPe_^bOlnGRkCGkMLl`IPdxb@irEf|9nxc zuRjjmA4{-0O<`$&-eVTfx&qF`0ZT6gJ?*n~`hST|8;=F+;qglUfN}$)GPD%-9 z7OrnOKqXa5DV0jmK^int;(bb059ynozw}V3dMFd-8xN|jx%qe`LE_S<=czB0PcxY@ z(^7lt;Si#5fenZ zHGd`(u>^3`#IXTARbMYKJk^H7qd zlA6tH2Wuu10(ydLo~kZ&3hiX{^+SoR=8ThgI{c31pn1aaF}0)Pv{{00HusRMQJT%2 zv-*m)(VU<>eS6$VJkFfWao2M@Ni%l{7Jn<$Z0<9%8k*zole3YV>)l7Txw!^Bqkh9z zJSNXu`_aQ`YoDK;RO@T=aH#7ieF+^-+4XaN-t{MU|Gevqn;lMb{DQ9kiMk+krY!m+ z1-d+ix&&N3AVDM+I^6Y#?%i^@hpeFIjXtLrHTs$PuGmt5Dx}bAF6bb-EjF4*ZGUG+ z7VRPPNH!jRfql>%2NOrlQw{8Ga?RX>=c-B@%~hTGBb(GA^Cb4jws6QgLM9yPm50oO zv!Oky`Z8L7(QGuQEH@t#RII z_j~ZH)6SdbOhoVZ;8{oC@2#JRZ4*G1Cv3m_MKCor;j^2S2y%_6F($0Wp_xdIc!9`v#){m)QCSD3{Cp20{Tbmp?%VKetW& z2JH!#zyt*-w_*ne^8o=fmx03uD3^W-2Q~sTIhQ{{2S2y<2?vk@ml0(JD7UQ)2ay4n zRS5?vmw>?sAD4y>2PBuY2?s&9>kbD!7MFw!2PwBvB?pcImp%>$DVGQ+2RWCj4hKQE zf+zS`e3*D+egIi#`WS z0+%6N1t^yhqz4=p5cpqw`Psg@iQm4wN?{-gNC5!6eF&FvUj-BcHa9YtKS2jS1U5A` zGMDl60u+CpSqWSd*Sen&lR-s9rg53kGts(N(AsKiwXStXt5p#fK$fsW*b$H&Lc$3l z?EAh1LO@*DL`2lmYHjsatV^|5y?U*6sjbTyJiPnf1g!dQ+k5YO!QX&0XU_S~|NGAW z`+r{q#E>C`Kp+^qZ0#D`&0F8G+3=a%*U9fgtIvOA?jb%-fyQU6xQW~(Xa>0P1UEsz z0TYfDa?&AqsF`rT*^vI-xNW@X%8NeH1cDIcj^wWo?^ne}&vXJkZnKBUn0j&YbsV8LtbZ%dMsBoLs!+ zVL^Z1o>C`2SLr%y=>}`*MtK;2*Hb!O?k9DYc{usFN#$rUgX&t;b zSn4JZl)B1-ojiSltp9nBzx{usJkZz4XPK+qS+>?y<`?W498T~bh8R!0O-v_d5HpE) zh*^XcVNJ{?-X-P|?-BEf4~P$m1;j#PF|mYLN-QIm6Dx^T#2R89v7WFYHV_+$&BT9a z#1>*Jv5l}L?1){2Be92YBAf{qLPod|9)u_1MR*gwgg+5L1QNkSC=pIX5K)3Bf~SJ# zLf%vSXDPAN=(8b2f?$LoU9ey9waGG*N|S5CaYEIQ;X@LJ+!rN^ei1v7V@OZaO{N!y z+79&|Y8YldtYNtA@Eo(LX4ghIkGOwfE;s+n$gv|cEr3OU#c7Lsqns?qS|(9*sLOB7 ze(Ot#ND?kNJKA&f-7$;DG>&x~XF9HpUQKr~%JGxOXG|a_EJgxFeLj@8H#mEAEFEZzJ zak}6G$fd?`w_0b}a2@$w>eW+@T+SWI37@T`^S;PXH`ty7kSqCcR_B}#mwB)CEeo&K zm6X<0?kft>f~ux&n8BPp>AHV_^&vMa*C0m2r(HV3|)@q4_y{O?fwU0Z7 zd?d(n@*`}%Xy=~r2!OsJ@r+oJ7kMr-aVOjVcRjiPw1_(BS$RZujzNDEGI@yJV&|$Q z!SECJ-N3Em`h?H~Kde|ox@fBIq{o@W2}AJVDzqFGJ{^fGd z5P!L6O^B|cyhaCb?~vc!GlI1&6xs4GqT#wjIwA5-lbi_a+T|4z;OAQw&{&?ItI+^o zxM0aAK&e!!lIVZZEo&k>c_qW^fw9GhNq(0cs1y^ z@G2KyPK|YA`-@38RqSFA;>B5r(Hb-b%|sj6scMNGoME#JID4#joy%ZSOxfA1G8$N} zo@_|XXa|TCUpec&qm}(?36$=n2VyVWz*+E-XYgt@g6V(MtLdfIa>qs+$khoMM_KL{ zl4^Y;?yx&~z+-pmb_S2a!kJitNB%qoS@s;&H5ynOl3I%BA>lB2Ul^cjT;%payBT|z z%BCRJ|DfXN5&HA2!xfF7sj^LXjOpkI+Fr++_qp>laLRz{43=ohUF4=m)_RqmdeOHA zLY$X%6B@LiDJcro0}x24x^9CKE-q~ zs~7vBFj4=lSAZ3~0_?GvG8v2@mumE(PEdCnWt3%hpr=ov5+X|J067%7lwRizH_}nc4yojZKiy1_{u}M?X9R3(;fAW`~`d`~V*H zorr(B>{k?2+en`|f9TsQU)in%75$cy#UJfj0I11xmwb8syOTZV>siEnC@PHa^8S=I z?_0|Q-)cZD27wWHM?IRV7xsABI?@Z3ZLGnYw1WAKEK>YPKFsx* zH|UP}G2SzPHA;Qyj&Wl2L5U3>Q^cR9D|~-k3k)dHAlF%(&AKW zyL9e0DZoP(cwNW6q(cl`&l9)i;0ajC^rS-NS=JCnE?4F3XVJIF%z#HC5lOvu>u6gm zpe7Y&C8wmZ;qi)yXgZ)|Z*@&^Ni`Ti{pq6_H;|~VLx&_c>ccFb8*=Z~-7UFGb=`m9 z0?=*=GX3CJJZ#7ANKY9++sNd+LvhUv8g=P!1v!Zt1q+j5yaMcVwU61xY}#3n>%+!r zl@QX=FgBdU?PNHNDa_QQWokh|?tx=Bn3Fa3d$ZUg_f&gV+AU?9+!6Thb@8!f)~!E$ zHkhT3$7)hC_}6vi#rh_{ys&WZxIKUGUYUbPmXb=*sAmt5g)vrmmy9uRfnfr4;X5Ix zL?22F6FFP56lR7-r= eqp~MdXDVKP26hyidmXAR~vdLD}u}ArbvpS8ytTlb|pL6 zgW^EfqTS5&<*Pp4UF}g8#)bqYcn8tWr9R~mfcn;ddz7=QJ-y=BEodwng-niJ?e=c= zDgydVJK+pwi`YjKShJt5OwY>50)fp36_w1R-t$)uMAQdWv-!D(vZHF#WTiq8Nr&e} z7v~pcRRH{{RN|%x;ORmh;+=mO&QR(yYk0rBNn2e|%2pKVa%-3$;X5HL67`EE+ZNkT z2h?(lX-nF>%L;q0v-ia{XbfD)4r+-W1JV!1^2NKtzJ$?+5OT4KM}#XTn^JQwgK~oy zPgCM)8j)8yIS|@70$)TCfA;h>#fs514VuPd{BlN=gD&EnH=puI-{OBw2yI0sFR2vW zx&-;3w@B(|u7@Yn^)axGMIq#0W!;nBv)|$!4pPuPF@@et>3OeWzoiw{FtyE4*~0$z z>RR&Y_ea0{vS5!5z~O&1&>THS>(2^uQKJwYLF*-FapOADoTCOZiV+tfxY}P`}is=iBAzlgXU4O##4L}7BG2VKxHFK4f~9HBryb3 z`1u6{d-+ua)axs&Yx$)2^=lLRO8HscJ>elg7N?{8$PO+0y61nmxaMJ859MbnVnJU zR7c*yY|F`jP94H+y)aWT5N286ydZ{K<`dip>{Umk%PgXo>T(R4@ zqWKG_mwuSpz#YFXd@=hEju8G>?5|RWC$e~7|5tb)cUpf`nvkNAGkDRfe33u~z+F>~ zleZm#)lBt~frLR$g&ox_rz6#Br0vI|==8MMd?rtuo2z9}W}i@f(zlFm9ArE+OP7DW>fBqscU%3 zYt>TtuaAEgb@b`gqi4?M*lqoj!}Z1~{MQ2qxQM%EfJQyjz^!ed+WHdufP@bVhutuM z3D^xa4t!WVhPwjT{v~ApP_9svADf~MWAH*Rowzs?s!G{vr8;FV&8OZ!hmud986>x| z|B)yrD^;1z>*(xamTM!cVaH=IKu0gJdr3q*a=(8gqUjDRf?~k`1FV0;M8@>1e{fyL zjpv2Wy*2kx$bGAOR68$wu1ioJCNE9K!zRwgW3c3b6%u{h(sry8gppW@O`SG}ZrAAj z0d=P}O=HNW>w=4d!u?`pt4})LMHA3yG#+_@ckW6S?U^;#-mk1F1W=~IO|at_O^xn> z%{70A!TzfH(j&|_wQCg`wrr>R<1pG->*=|P146IuwlS@GO3{VOkPQb5JK=2YDn!Ui5z9_^$Lz%TSIps~7{U!kid(4&H_ zaZ+z{p$9TIS8w==PuwwAh1{0W1`l$UGM9fpIbCFpO6?C^oNa?<@da#6H>~-b?a$`Z zcg!r{;U(4_z6slywp&nncu)-c)}i`3^d%oY({95jTb`gLPbj;-ceq5!!-==?WY91C zT@4^MGA%E?dCH@z{};VQqID!1iH2W&%Dz3CTIdL|30?y5EL1wE(VmFW5{Ly3yvu)X zVOs-wM+f!ju^~*))7&MbzfGAAmZ77j{)|VsZjRe-2TqgJ;Xy9>R-5F+_RIcNuq+^{ zjdn+lCDgwzP)B2O#fKkx*cWtqgP5X$!qk&IRMFXVhPixpJ{It%yo(SKHaR0Ma)(`f0>Ctu%JCX(M&san zcnuo=4#>=fxo=E~l>D5hkw)@UBoc2x!@%90bFPImaeUR73{|-?ERy1J^>{tDrtu-Z zCLC{P52AVLrJxm>#O%V(V_BI1(MYP}Yc4Z-uu6PcA)fesfyn2MK~%Z%dI5j>{^ddB zy0ER}H)`&dlWy;ej(hEDurZcYCdQI#)UVUf$P4X<>MB|M$sfUsXQ11XNSL%Q0Bm%# z-RH?Hw7HE4B))j<>a~uKw(@~g5vofxAYS_(83-ga{>ix~Ki5$ueIWcV z0&El>A#!G0Qahr;*~C+E=dpiDgXxvh`=@Twk1)>(GXTE&Mzm2rulRY222Fh<&LFZR zFB;quGT2&gxOX*e1NSt$0jk5T<)osP`JwcBow2bqM}mb5-6sKF!KaI>)j5?Kpw6m? zrOX{P7UF5Vo8}I%*2^p_yuG}al5%fx=8{Hlo#Q&kom)ad%2P4bizk2m5n26F!7!ct zPLGKDsXR?2CC4QM(>|3^rIlrcwML2zHE>>aXnvib=L~vyM#$Bm4U$`*-JVhjFsK); zFW7zTOZuD7&)h=GD)4-n7R08i6Z4qDfrf?MK*J(IrHoAk9$Q2wcC0Vh%HZMey*p(| zi&M#7cE7tJ0TF>W!wP?t1`pHh*ecJR^eWrsR{Q}JA4hBwC`^GFQA{LE*vsPWWF(Bs z%T%XkXMnWyv@Bh->6SAWqrc$mk-t8A&g1eyoQ|7TC1~tMiQPhuLJ~=b-(T?Xa*&#^ zB|Dk%$=F?Xh^{Md{s|4yE|8~!1a*coW6;uj1BNP;FftOPsN#R)l?+tEq%@Ed>6hcc zV5!fNT|1imG)nf6Z$S>qOHpk{FUNZ2he(Qk1UIW`K2}n;mz6 zqy!az-UhlN7q5Sz;e*v2tVaK>yLR`GF`-yJK*4-gp*jgZqc}>?nCW-1aK#?`ox$LT zjNbiUg3h{QhtDvj?Mj}Z9aPDlv9xbRL}hVp&Ver+j=qaozJMQ#eQ+hRT=M`>&aoX` zc`a@1p@R+0w`eP455+Oe9oPqW@bqu%)uh|U2Dhos9iV?7bzi*PSr_0@0?OQ=gPoD~ zU(!ksH%G{M_jyb5;b(GvNpW zvI(<9CYOBlUtEHE>R0p(jgp-7*+#DNag(iqHwyvMp&16AWo$^w!$+Jl$9a~u(o{}T zy?1c67!SP@-VP{}Zw`I&-C(Zg&ni0bEAMw$ZFzt3m&H$ZK2iTt_Jp!9`e%vchqafc zl!L3fo^#*R)U4R=-#zuV^rOv7+^Qn0^`+&tP2Tw-YH*_YvZk1!ERR=TN|?OT&nYUB z_4Nr>ZA>=Zo05BvE zTxNg$vVm9h<9@vRvoUhub@cPohX%{zPdEJJ_!N!)iK^kt|J4#7u`(=SN6cQ+grp@f zlEJIQh(YFs1NfC%!G8+ejY-8{GQ!#FB7^8YP^5> z@n33_JPTMf6F(B|%ScbmXYw;Ljgou<`nK|9Ltc}5ocW7OFtqPIgW$!9K^^Pu34ItJ zAE?>Jzu#RO;IDuxMKp`w>vzVBxCoIV52k8peHX0dSHnOlk~s}(-s6R;$Q(8+y7*H_ zC&%C!{h#pTBaP$JAgw<>IG%ky{_}qlD9dA!TmN%Wlr}BCkjYQa%1dL>CtN1_q(4Ix zo0b++$P}h!2RjAKHap~lw;PpZPUgq@Aybd)PfNlVU2qiYVp;sJjc9e5bS z?V!ewAJ>_kEYD#Pjh~A4rE7Roi_&;{WS^miXShKWtxbz9;tkEt;jJHmE@V{{wHggI zmX@4=_vB$dDmKJv^#LpfXo0S=wxP~2&d}IceMW6MSok_HicNzaE>We$MAOlVn3yPF zvux2lQA|F}f^(f)Jll#N~NuXxlPX`tNAd5LNqpD3F$U^4^H zzQtQ6O(K^h()a`KQfq3N=a1204Y{rQ&b>IEP$zLbfsQhZZv<6@gv( zDp?VW=HeHki4MLiS2BT-xsc6Bt;ngRb)f|zVZqTpjxBE8w>zF^rvYTc&8s@qlx;A= zrwi5f4buq@-$oU@u8%?&B+p~ddVK}{=J-)LpN%c;t>jUx`*PLv?etpB)Q*K*~#zSy05|GsN2e%HM%Q^rfYhPB00z>YDya&}f!QeiG1HJ!2aVjA3nE2Qf z{(Ps5OHrv{6oW@2f%wsnO{eSX68BaC=$zn8dsj!6=Qm^>KEAzU{tP^NCl-VMXtPVn z=8PC87MJ{CH-djl;l}Z4#WqZES=XXN1b;DViA|Ea&}t9=_}HW*@Nj>7YcnrIpcc|u z@#%`F`HS$dO_e*37|N^a0CG`Fs>5q#|7NVdvcdocRy%^G4XTz`%lUCXNP2>f?)C}^ z^fjuKnyj4kbTGr+-q8st6i@*NR7(Dht9&7WTt@$=LwQr3#96=kj_Ciokh$^udkc;+ zn>v9Yh^YT&Qc-zmpc~Sn7Lb=1a9*S?d=TJ_kWy z9=z&eSyy(2oi`$tY;@IqD0R`2RJOOmy)a@$nfFBQH?NFUws?E#dR49Uq4uUzHZqgT zu5T|+^^-UHXbaVr`pAY4G@6|4xoJ+y>VIK@H=D6S9ZYNE(R)@YHnPiK7baTvmq$L_ zYj&4LvB+@lDw4duVH);039 zf-@oDizI@U1p6+aMH11D!3lxs9DjQxXgby)=$v7X1a?dk!81-hp^VdXxFoUDl9XYB zBxTrXNy>=G7dRoIMZyV5=LMe0Ii0NA>5}RFiK_@#cAb%ZksQUK6eK{C8Qw|v4%*k( z-bAxrZnUOuY?b@EtMGa)Tl!dee*l|}iZ=>nZkP2C1rWE? zKnGhJm)d&=ESFnc2SB$*d8)o#5g6< z7h_`7r*TM(FXj|p-unMGsEIH6fBnx|7Fgps=kBx5-c=IH%8HUmB=#$pEnKqNeVqHE zWx?CLgC;pUxqk+4^|2h8FRDaGWW$LLlsHr(a=k=eDh{;5BWtFDy7RBz(*S)e8TBa8-10SfGmh4)fjW>mBavqlygj z@eNZ&`1`8nuUx)DH7__QLggN?$u}t6SLNiSQic2as{A7&LZ(lg7!m0=Avnx$;%0JA z_{6O}Cx3-cv|Q&j@1w;loZLT{+OOYRza-fD$Z&G8aanyLqiJCx7q$W|5skfGilJhucxpS9DEVDVmWcegQm&T8vLdH}WUJ)IUOv4pNNMR@ zX}J|+6=ii_Hdj_De@||pBk23q^R3m^Mb@`_C-kxFv$T)qjnQxHxAC^==sUe{UEeO- z*?+bb{U-J^_Pg6(*8j?Yw+DQ0H^c5WlgvCFm^|>ZVyNPzy{rA@K_dpG54trte#qz{ zwMtgGRe6amcIe}f6 zEJ3SFoyA6}<xYGV#;)xT+Z%BV-fpxllLq>fS#+vxhZ&rlF^KV{;?Oo71|C|aes`< zR5wwurrjw zLiv-OGuH9D@VAO2ga_i`9CnAp;C~^n5RlhCey=xLu2I@{GFr1Z&Qw79L}PdN2z! zReX%esIO-0jG1*jS)X#0ADg1rr=@ZqERh{uv|#6a7H487JO+DXZy>)R6FveN^aGl= z74x*MV!u|qW*CTIKnV<(1b+jV`(haMR+MZ<$*~4~Vmjv@x;Dm>#XN#h?I#h~gQBTS zrz_@}6|wR9s1)T(9NfazIZHXF63?HFX>5&${4^dWz}tJkI+wSFD+runFgQzYfU^{m z#a@bo{!Lz9{{CKGP5uWDHZ>jOaGTX%_K^$m>?rW)zHp`#Obv=J1Ak5}UANWWYtt^@ zj~gq>OeQWBOBQ-W#ae6AbvmswxiC3z$8WcQ=WL(Lks#jbMv{X#2u4XeKZUyr2*G1P zf!ACMS;F~=2=1=HB z%r-%k63htd6P5x(Hh*cDh2mp-fnJn`T6pm{nmPCH!TSZs@+@1-N?cwGyBpk63wU{AFM22~Nj=tyrg2~Z%| zk&K4HQ~^c_2?F!H(+_qj)N;&422aL|SUet@PRJh?c+KVo*ng*%&rb0g%dLO{7%ykq zU}~K!?pw+W@~xni{aa!w!A(+vPCGf%%T}z>wu1X!m~NId!oZpbVDmsKrVu>rj6vyf z`t*1$w>D~7;6fHV8equBJe-hM6`)-W+N-ON^5)GRJLj=@%9P=F09O7o7N)}FgU`zN z@t{=TRC#8L@qa+&UhCGn)}neAdS~K6{zj6NKS`=ufU53g8U_;u7%E6R-w{7lSOV<& z^<{vByq=&#YzIh??hr3v7OIcZ5A$ConM#se4OO6$!_?~caqk@jb^jvwekwqSSwa|% zx&!^B;s;`<;(*`bnPV{Jjb+?O7xmZp={z+Jb|zW#d4Hrc^THH(3bcUxKB1x4H~F>M z*+`$uC1_G(Vw7G@F?D+yE893*@rvf)XW#(C&3B=HW3=5VQ2K!K4h&O+EU^;zwp?)6=BkzH%HdkMmq%)ul4IjD8L+i!P@+i*_`hj7>Q;9hcnahBKzBX-ro#=j>)&ip@Vc8UJ)C^a+w^@c}VQ(~o zZC0KyIRt2n55#X4_91gnGbMosxtOx)_MJ^KeeP}m!grBHrwkt)2Sf!M46+FRZHg0% zwLmMAAUyoyBjKSf-_Km4_~Z78$5p~uM7`AE%n==4lYY`%XKZ2uL3CcTiCQc>sy&Z8 zN^z=NxRLssN>>Qcep$g_E!o??PasYUwch7N!V({^9SLXt1+gvjFlRidl7QO_-vkYH z>$9#KkQTa2Rc(OU|45l~>myCa3Lm@l>gpGzK6VcaOBY>LK}T1!>$u}NuAGyA|8%{7cb%k)f(#k>51u4~WR%Z)@r7@z#Paqw=S}dRdOY?o4 z#rO9Ld^#zD5NzYL2g0p!*D!JNPX)us=xYr{z&$5)J9nt+J#*P{--zV0?2fcByl<$^ z=N*U<>OFLPfElh23TYdyv5yfU`dm+yEe`v%OPK??MZlZ$;au*~%pBoLP>#I#^h2?* zbH)Bf_xK+z{A&L|OPxf}Wr-x?XH__0pV|!!fG4dP1FLgy$Vk}*ufv%Le;qRTitO0@hLl~$peW1mBZL7}Vs4V=+&c2g zm2*F*3Bt%Gi8=UZl)~ruQ}aytJ59{=+oQ;ji~I>%xjiTLcOQXf3jVYbB=l)hCB3Na8WWU%mMpjpX^#!2CgNJs1q0bXmT{AsVM(q^@xPUsM zN)Hpl+ZXI}djcs+CVOXZ)n7^@re^sUa~6Cf*`#Fu$kr5kSFVUo#nwvyCza8-vcmvwM*6p8nmmfbFxXph#OD;_j6zOx0g~?hdGq;Ly$bL;z<-`Q_ ziWcALh52d@Py48Ocr5;%%;KFuc+K(cnzoEkb&t*O2#fq=8E%j?VG^(7YA%iYa>1DY z{8R8|qgI(WbYGptQbJn>=(VIa^T>a<)_>2eX2JEy;wtGWqeQzf?}$872yLj9|FEgt zubX5|X-GL)`_eDzAt7MFqcai;$NAkPS=|Rxz!fe%Wc@7f1S*UoKRh6=Fd{wqaSry8 z8L}ZWrAvO1Sx-(9a2I)}Ef^pBFj2WOjFs^S#8qQeZ4gbm)W`5y+D!*@Pg zB>H@q_D85@;|IXuF;sq(Fa_g4EX0S;jhMZ)ejGs4@~(hG?|oD}kApOR3zK{TqP2JV zGPb3zp->Eq&Q$l*+Tk!ltnaBALUkTL9npuxE9m|eQ^gzrN?)o`Wj*Iyk8w^7d4Fp` zB-tG?)^~f^&CV49@>iAN449=ryTrc&N?r6+4C;g51-V&}H!OGhUg7Q!>ykfo?*#}Y z5MW(F=)&tPm+&W6`U%0fGIueR@&c=V`l6+wkUx-Zjb(Zp{musT59skV4~shzgn*T4 zsP0dA;24Mk{u*aGEj|GT{|jop6#}xbswIK220@9FU5#)#KO;a%Xs-#Dmff|0FxvvZJW{#HJMf znc&Rpjvc!?-fya6o&9v!s%eaQGYE5j`DYOPaZkS=(1Bml^L!NK%u&;;`h1jSLnO7E zYpC2Cz%VQ0mkj<2egw~KYh5p&9CvSa!?&^<_*RSeyJ)b2|Au@6UZyPsBA7(4jAr&A zm0-o7Ihjn}(wMzfP~~x@04weIbz63Hdb<{y>%vN`N@A)YfANw}Ys}wV(^deyusI{c z6gd3|P!%Iw!^z51kY#o3UK0!B;xNYJxfo#0wb|LcgEnH5OaXxQU~%mvCMY&7r!S8i ztzJgqJZYJyP1MNE9?8`2UH_`X-(}tx*m)Fx^{Wqf(8a1%w^=YPxoh3FB8cg!wiQEu zG&m$A>}c9&@_F~ZUzhMSuP^Zmv^quoyYw6Z5J78Z;1AJDT+(c;==Qz3^uv9Eo6x-I zi&^PWyX|L|8X8#`{i&nW)UJSZEVvpEX+RoUqJ7!hVfY#A;B}aOV8aA z06L1+*rpI+ED}mShY-Cj_JjK1HqceyAl-W|q3h#s6jY6}P3_j*&5;3h?vDQUK85bL zM?z~)k2U(8iE9A=b?Z81g1A+{mg^V^`fM-fYazDA0kq{*F$m-B>}m|hiA-T)px9fBs@LXmA013A4S!*U99W6#TL`8R|(PpQ8LD&}+U{<-r6&50WcpbV!}buUlvG63ZzU??wad40xNc=NTtCBMCy!sS<(*4%;9HS- zb|%CL)9~K0vbx;0KDw`F{=Br20x0mp*HaZi*)+xmnkU*d+H@mG0W+{~7!+xc#5rHC z4t-C-UCc3c9H#X&si|kSBn}J!oX}OHho~{b_gGH;>jdUughS7cL;0WFSu1v)VEw@y zY9XqFH&vfgYc}guQ)@M7Kx#e80?Cot3h3n4q8-M%N1wVxj5;#xy95mu=V(S zxMomFVr;2`4&@&dmqDPhMHd?VAZ4BfF127jV`SHV&MPl`Rntfe3=FFPX>a?w8N@%I zOIo?;=6Oo5p=eEvO87WfC}}zVdgC`|25a$YpSYtQq`<8jI9}YN%qQvwPV^{xwU;4M z_6PMrhEg|3t@5+);@<;Cd?8-HJ<174lC7AP^k`YQyD;)_y)d2*(jgNk=I9-|v!T2W z`Zfr%62!D|5t;))51kU`XQFwQ(RGc1T-k;VEof<+M z`hV8-3ce$y@VSqw#{6oKsD`tmkvrJKn_JA0#&*=@x&dj6AtkmZ6FqJx<|h6@BY>bB zxw8;`hpv>?0;O`Gq$yJmrRCp;h&`=;)*hE5>4Q(@f6eBTY3nxfeTB~zx!jY#I~DX) z+u7S+u%`a}6Esa?ogcDIJ3s*JPO>rhGfH9M_x*eC^-l4zFFW)DlQQvnqplpDcoh!6 zw#9|S+7550O!X`C?JZ}xg5Cx5cI*yY1>|tEZeactgZnnv6~sFfc9bFYKwCl*gJL#J zyIAkEUS+5EY1-`?pt4~FrHA=$;HeW=Bold=8_|)U2A8&(f{WosG?U%B0h&qu~IQ z!`F`)sdxb}$dNzP>3|0yK>J5X#3MIk+*Hse&5m;bYo8+qz)?0s6U^vW`&ogCz{YR$ zs>RkkPt5ovc!m)q!Y!LAKIoUHqflt+yzTcWh|OiIxgrV)RBK$Fia5eMM!C^F>(eaw zsq?DG7sfl^qmHSA8=i9p8Cj86OEdbZqR0k@E9c)&OE7zdg#6N&*DlfcYHnMniG_?m z{~aF-{yUCc2K=)$$drW}!=>+Yxo0{iAK{8tp{Ja1E*>&xwgX^S-LMggoYz8d^wksP zaVGNYfjIBM_mz25a5d%jCZi<*omH%rvVQ8PDY1QCBmdTsSGc=(^fS=#$qvrd=dI6C z-;8)~yM$}snw~1MMmGnMi7pFK}(O%7UQ|{>2Eh- zLPzY@=SGO$5=iVlc|m8qdp+>uo_;YT4jq~mUz*EAE6I@{AMBZEImxSks-?wL)>At{ zcm+JysdiHGBtah!1R)qzHVo~jE}to*{4J%rTfxm@0(Yz555j+1Hsa>?{T;@w$5CHf zVEpY#2Ea(Ch4)NHDySrgzV7oSj94B7GG*3-|T z^I1hcgSnxPjl7`%H8m-;{cldA9s~K#Dw7YlEx;*+0j3!tcr`}H!bbsvv>B&=)hUhk zp9eM@PfnVu7xwgs^9miWR21>@SZ5b&>`mt@n_e64Ndn7&GZH6wO#(A~m~ei~O?~#V zLO8{y|I4WrH<#N(;?O~NL=`>I0%0ca7>Ci@jtU{%g2mk3$z6TRs(GYB5QAK852x%o z2hha?9A-6S0L|~JEaIYiqO3baa~oh#pr-j-igAN8_+(+)xzFZ_Fk7#VDr7)#DTZWF z(udQrFYK8@PdSZTWwv5T;ceuT5w9&j*)d6KxnO>ya_g8U zjCfBM5#rzji$b19Zsv_zQWv;W_$qjP15g5*3~H~gjrP8{tX_B*(xlGJlrvf>Un17P z!XQQ6+@N#(ZhJggRq5b@L0=w|c9z5Z7vc3st&y}^)HO8<&xqeBDUs$T`o_?`9RIPm z$IL4-uVICovohDfP7Ghoqo znx0$MR4Zm^bfFJphzz{Qm|+RmaXfua93NR*aw4SFAR>{5v|yOq4ujLEwnwoIzi2&f%p7ZE}D%Yzp$r z1Pb-xcIMH3Ea=qxj44M6^rpAu9d6)09 zsh6GG5Z1%;gT**R(re^(zx(}z)c`B>+=>ce_S2+o^QD7$} z^vm7z1lAS5qs9^O(Ba@h6|;0KjimxUC!&Lo>~`1Evz=KiqY>7!Nfv_@6X3u+k|K6W zNQ$B6JazMB$?UV@S;79+pT$poI?p{n5cSB-Zvg|S@wRUkcUR3$# z?=MDP@RNN8d9jqvccgvNPyqf7{Ls)8m4RPGS^4O?(zsP!>Uz{D*BOFd7-Q9&s4T3c zKM00}%}eH%fvKH1QZehX&SZzGc(Lg+t*LdXg6-V?^`8P7guL9qyI4AWiAXfDARu>a9|v) zK;boLN&xeR^sq35V4s=5uT8V3dX6~;OYJr9-JWgoE2j`KbwyuqdFS8RMJIkb4g-

zxqGGdYxOKO^xlWr>(KCp=8LOURftgkMxZ$NMXgjtlWeb2f~n2R>3K-Mbh7P|H+C+X zF7Ca|kkpuP>-vVF)~nmR_e%}0SE)Bs4o6>+5$%Q_m6xe5Y_XAtO-k=fOXJB?j+69I|8Ks z5Pr8rhjCRzO{Aigyd@`9X#K{5-}y4AdP&DgA*F*fK-be*Jt-f$V;Qo;r_y^5IV5SkWfi3Cju%gS*Bb6g(7E6>CYWIv0?`VF? z;n5CahUFLHHzQTw=6hmR#GtvX1<0&Geh1#?kerbID%1|ubkiV}sBZXQ=|4oVr29ig zUFp_Du*8VAXh!3#cMLQKF0tjIbLP~MVUfRZ1Y|I%6#BDfvXY)iki14B zRK?5=F;neg$qguve=hYNft?R5<|vkG2R@I zbWDA$Dy4Uw1|_tFzvT5Owb)dE(a>Ss9-&epn0LR>UDM?O6ceKKzE*s{gLY-mLTl1f zmdL&GLIX4CeR{v6X#xU;f4;U+*_P(0ZJ%;>p)6H&{|2MzS$ z|9j?nRraI?)LY#7?>oXp3t+AZr`}uq|V<7Ok)y41Sb#ia+w!`7 z@U}Q{rLgVBcWO7%+68Gdexx@t5&v@=bb4$C;IHonpt4xj;M}h2?*4Lqc{zNI))(w} z4!+{^dN_T5Xz1bpxEVRCu(64oc3>3H>pnusWfbtg2twlL@A?!B^FvRkiQ`M=0+$(x z_1GL6sJYV6;Pm#oJ>I)ZUOX82+Hjqfr_w~@H2WLb@9+6=GhfcTXW@Q3KXn?fktghN zTOtn+co#C8YM4-c^puv~3+gO0cF=ESQ=u_

lTakd}@)tbj&-d{K-k#Sdx9}zdK(&Crf7i>c#S<``s2X7K(ZuWZc`$Ga zU;8B!|6x#9HIpk?_1VkH+-bKF8zI~)^=Z7lexBuk-GQ3jQYw)uckI@@e(;F+x~3Pl4&*6UDJ#c$LH~MZgqn5K?z9auln`jdSfOvTrjGs-r>iIGjaC4%}r*qph7*I z%qO>nz2k;;@t5ze?PE(q&i|F+@QIfv zt8=#8zlglGmN4M-{j*rfYaSk9#?yZTkWO=`{;7C{IkCsk`frjeBqeSYOD4?d7zTth zF76H~OPB8$V>! z2s12vlo{b~iASkYRX7x#Oe`>?0q_Kx5X@9lu+Z+Pp&lj&hVI3oU|YNgYjw;Usx&HY z&RJ{PxZI_g93ycHDLg2VCQ*6}H>>eIUH+fha{Uu$f{fLc9W8h`?}>B~s6TeJjz&tb zfhH>1AEW3dO9dU#-*x zkX&h->)=Kx52C-)KT>p+0nz=wTRFkqfamkMiEZzyf%I&Bz-z7E3F|VUQ~_hjDBolw z0i9pBuF9*`q&T0A(uqq9Gm|pRSqyq9iYA{XL~|;b%OtwRKy51kyZHmhmT7?+6aEP$ zI=FA@1?8(fMpk?Kyx9*Q))?s z`o$wHDu;w$FSt}I-`S%&Fk?;Km5PivuKDvVMXsX|%DI)kQ05}asiA_+(TYG<`XUbZ zmtA{4&eHJwtH2^L5-@*CC5w6rbr~vkSH3CO#;58fS86*zXbN`G9lJ@wF~{y=vvK+5 z#Gz(}P>ns?fgKPDQ2Vj2MRSL}HJJGVuQN%cpv?kk9C|MV!L+1x z4$`0=q{)hUoBu0MqC=dZ4k=hQ`Odk+nij^DR+gQswgGPPp@IcrW?!oqPWRj61P4uJ z-q>5BQIllGnx=V-l@=kZkD;X1x13OgII}}ut~h@jBSAV5wm5DNx~t@Jp$3bTsTVPa zGUN{rBBb&Fpu&)eM@6TGwxzLpBcZ+bA>vvr0GBG)<95>lz$x~8{XSOl9j4gvgV#zV zay?j;l41{g=;8*+$wwvBmN<=_q%D$?+=p7OHR3g!wuq?|ZtSWG4hSo_7-|Zomp<+X z0fvGPH8F&rVy*I%riFL4sbuZOD24s3A;qkz3lFaw;PrlfE>wY*SBGh1!}9SJBC1erMlYg9~4>D;}?a z$ajMSAoZbxfcKONC1n?AFa5Dj|B_n%X!ah5vvNh4`{^w357a^FfF6?_GP;myDbx)I z?(L7WP4meuJ|#=aM;~gfOzX_JVrFta{?kk^qq0A(=qe&h%0*W;m!yvFz{h907fy+P zgO3!OGYLw7gZ~Uy@vm+4W1p&yv7b?XmHQ1(0EQMO{K7wYS!Ju|oto3<@MkScmG!E& zuZ!g4xi2wS+!+U_x}>iq@4t{G03$X{8zDREN0g>mWN^owzx6+S(K(sBN7$y(Euc(lSc4g5Oj!Br{31BxCR9Bo zq^8FJ_UiHp@3=bt3Nf5hZQD?n1nk&-KpA6+K<)VX+mZJv#<1w}M9DD!hxUqmifECT z0DEgcZj&RalJa^jlvZuoG_0;Hu0uDZhAh<8W&rx*E_+x#23-IHKEdw!AN^&6VN~dC z5FHLH6!LbGYH7<3gs(o_WwO%1RC_;8oA>8ch0>n@+ynC#qOWM>A45j6TRQ~&0PTis zyd%4x>-#MHUm8g6pAIN*+&;SI$RKGS$RLdK{?_pm#}I~XK(qjxFhgOwj2qC%K0}0d zr|E#&LaiQqIh#_pF*muXeQbYMt8hMSB%>mNCFNw*SXK5o6L8*=$xQLVmm_SM8kBs8 zq~~L0v0+#zCEeyxXi{B==)Ha;fQv*ICi$Z|KXhB7o}ce41X>fE^KLOS(OB_La&M({ zEq3&zKJ>|~y;9Km0I#}Mo1B_u0VFG3mOn#K{|yYfq(B!Yx@0j?jw+3`YGML0JP%D6 zNs(oi219x*N`RlBvYs^9Vh}NLuXa}SY=r{ziFT%Oxm^{B&ic=tyw3n#Kn*6SW}t?g zrANGszt_tQR*yiAY8hrBsuYu$-$TE4k3ZAk+W{_#IfEF5Rhx+9uxyhdcM7I%udg`t z9`RQR61mCKQlO0L_H2Mx5$MSlQs_UJ9AUX^61IW-gcwyCw%~t;#fPa{jPs7v5J&H1 z;uPDYaEgo{9vA6a+hS4z#tX$tj9pkV=}Wk$?-ie*v#`@WX{2Agf722H!kwysj6 zVQ5WVX~{Jxc|k-r7<+p+VzdTXK_T~Z7JJkVLnmlu&n#JzwE3*q571NG7_TK`jMp4# zr;VkdvrbI6$_UpsFkDLr%~N8Rj^RTw z4SDOWFW7pyHke0NlSikmYJ)pULD>Z{A~t<%=^0`|!t+g811)b3DkI2m2cN`qZS1k} z)C4xsKC66|jVpfx6VR^@;mmm3hra6k0m3q_>Zb{o8-Um?OB1!r_2}?-5*?&9Okq^ntYe3QmU!8 z5LiK!Ed%jb7xhfqfTmOpSOgyjsu-P4A9Ip_hMr&GNNLT8I^ZOYyqJ@nzTd|JAG+!c zL&5_lI?Q`MO|-z2>VdNU(Q&I6_0lDCXc{AX^wq%;22)B$=Lu~ zpDO9T`_UR~yZJ7At;i?<)1Sf-sOyhZLZC;Y4d9fDYFDcT<%|d~d+}kYIhATdd&`p|G$-}#VxZ>afmYa{|8Ym< zJiTC<<-7I7u$(xGwbhruwc=1%>yUb=;5@QW$VKjSi$;O>D@NSqn{d*{I_q4{kF;aC zpbX`320+s_G872VEx3Fa-muovU1uCeHMeA2r;VXThNIOy23C%uYd;sX&4!5wqc>=!O^nwG{ay^@{!{ALEW`;^|LDg zfT|jC(Wy{n7Db@Ir89w~#O5cSU`a&&Sgw4)5VvdboRb6c51OI%<7@i5GT_@y;Is z2)C)sG5zcUrnZQU7~v9x59AE%4*JO>arE1|;(K!*eSxMtQi%RfFg+V55EK~}y#><* zrimCBt_p()L_mgxYuO8iLC612e)e67(Snc%ql5GXRqttQ;K>lnEBIB{>iFnH$)z z`c3oKU>op&xNhIn`Vm%#80eq(-F6KVZWJFFv-V9}SmCbNfU1wMSS?+aaFay9K}o>(Ih0~=5mRiDL01?UIky|om;MnniQ4#;Y4E!!Lv=E)a!QcVGO5reD z_@Ut234pFMa1<^0$qFM1_^499kr!pzt8CsOhON}$B0WVuSIDU3p70#DI|TkDe0#2`{13DXDJ*C6&n z)wwiSN%sc>kQgFN*S1uCNyoW>M#@42qfi4Wh2Id!qJ}J^QGUTjHDimV)N|m;r9|%X zPh(42B2f29CowU4P#-0c>pB@jgPGFiB>WkVDJ_G8n8_- zjWCbeWAGg96PQLTpuph8|1%e*qlBLxwhG5&Ww+x7i;$TPs$`g$|3_TL7&}3f!jgmZ z&=DRgX+Q=}U-=jx$(|)LjW>+N7$Iqr{XNRWa40~Ftwc!h05xEE5}S#rcVHfZ4+_~B zwp-)4Rx^+Ucb{x&vOBg1fPgIyNgDLEM^K)qHIDr(GvW!H$1V`sh2fj-MUaM+G-vJ< zp^!8;nmC6l5N2;UC~`hfZz!7uW;hj?JhuaUdes9%N4Z>e2;*!X({zL?3DfKJ&v ztVaQT{G6>1X13+Y_7Le{54ys=&A8oB5=O_t1|Iz>CK%Q9XS1I^_qZ*x8x8Z zoSFS0YP}Ef0_I3UDTp*b%DI?dE~tTBGN_jLh<$_ z$(e~PpkD}>0DaIVoC-@=jBGVwTn$HB$wl+*0ys3%E-;rDo}4(1Ro};S1_R1{qEz0B z`!`x4>sMlaem=pDsl?{C6e)-(ZkpLr0mUUEYPOJE$WyZ5pgHi>q42xDF-T%wyvElA zR;(&!^e4`OR1dK;MhqLzN{lT5-GpO;$S`sqXm}C>fDxupU81i-0rYbQIHZ`YAj97q zT1d?q@^Q&~1Jn498;8FtNx}Jf{-T$nZaDL|6(fWqw-uL~zi~Y4N zg?>B!cJ1x*Z2$a}aiGRA4>!ebkt#}WAE{>fW>@KtI6Ep}DIaDrqVa|qYb_4WKrS%= zv5ASR2@r40*XrPYx&(sg*08wy`S5hMHtr;)AyD@keQjZKt-;w_4)9kExx}%%n%0Ok zd+_5DbhT)@X$&|e`_l$ zibYV5vpdHxNycDuW@#SOHTMcMh#~rv(@4I*v-aD)CW~C%+jV>OO7fQwp}Nx&wyY+W z?&*vpQ4_FuzM^{!f1z`{HpKya-rQzSFSVsiDX(K6K0ldtN?Noj^SaU+P}azt#hUR< z0kTD0C+|o@r7CQ1BLLk~RW6@E#=}5>ck1fI+~P_@{I+M8aHSDcP0W@lHkV|LUuprsLs;4AlIYV z4@=ZWQ*%4PUeu@>LM_y3xE%(Uy@BcrKtr+2d!58B0_5#&(2GJPn+Fa1e3S3BJm1Hw z|A}zbZlm$4ILpC+d2BP$pfa$tN41J^x_5oo&VAPGHh&RQD~)ana|ZJOheXuM)Xy1iIEADhU!T^oAv ztV;*D%s3v~Zx8U=lex!_@Nm&EsMKhF@)fO;ixvt1vBaj_kJyx6`E{zVA)x1H?GW^o z_uOl-r*rGWZ%p}uue0I|(&)ZFxfRDiQC6{nyTiqKMo&@0+wvH>9>xUgKUh@ zbpC(gO3~=>{kISPkw1SnSV6Ub3qGB~O0)oj&z_cM7ZU!SM$6&UwpdXGb@_;j5kp z{^Qt#v97I6aOGOd7jiS;YlikiP{`67BmHb(za!oUGv5ns2UCG{pA&@RJ3+MhmS1Z( z-w2C~-)6TPv~D)q7#fH&Lw1xhGNyjD5%Y@6!&d8&L}NG;3P;uF%el84ke%U7--eEN zzT!Un_c_sdR|8+;iv~9?1o(HjnANesCiit6AyBIR4wAQmZ02zw#0e z6Kyy@09zf=Fh2-{gJN(=LAAWD!V_cL3#7PsMOC1GAgl3pRqxtJ^Wu&t6(H`B&5%Z? zDjQH^$>omqs8SWbx_{~=^~YEW@Ud&5$`0;o84yPYWvMqe;|2KWqmsz?##vrC<9LvL z&>-^fRGFU<`H%&uzd+{{gL;F1LFWc9+(#=4R$_O8{9)PIx-=8Io)eo2&<6RtViIs$ z4$omo{Op-;F2n$GqgfIP(gX_Hmk9V{ut=)-^15H{zi9w)q&Ap0h!)yC<6J~A{dj;5 z-(vr0f{9s2GX#JB%&?d9VR&~m>rt<<#PHoP=m0!x&sPIFYO}2WogrG+07`IZ6|4iP z%GbmeudKl@KABDAc+cEBB=|P-E+I?p*gy7ShmRJ!5O<(048Ohy;ac9r$u5Km0QJ}6?yeB-z3-Zq~Dd49Z5+qAs*wm?+I)#BmkO^ zJXs*U1{u6oy>J@ss(Ows-Q`$;T)p(A8r9R^eSLPP8tKb#7n%RkpE8$b@J}zctAow- ztC*WgKl$2YbHVE~!Noc;xDCN_3htv4a(LRH4LI7wQtVLzb)r_~)zN&Fc!H>=8eBFD zBE9vMXS}d}T!d=$7426)8%O}0FGCCjHUHG#W5K_R@wZmeTxyQ-CFeBo2YaF2RFeOm zW7Jxh2siJL=A13kO3T{(2c_K}_-a497j`EVkDA z3gRd8xCy5gX1{dsoeXI1?-DURU8_HV{R&5b=Z~xC_^-_v0IzO8B7t^K4Q`EI7lOeTp6!7xVI1*aQUBOz1;*CCE}(uYr}SKkz> zg+M&=M-#r6%|y-(YLS$x7Oixcxnb`&UA?pX=k2{*z~@1851ZZQR!v9y7qRpc*{^CA zkrrcbW9i>G5oKB>)R9(RCB!918K@aSSd!Gnw_vbxlZb%`%!o6MgRXqZKQd!FjZsCM zMYTmFZ~sdFFI-D~v;V*i*f-e0{DLV%41^(RBKbj5!~sDXavvrXl5hz5mknUCBUfTI z-J2ylpB>1VG0Z&`rjnJE9%TV%d<%mkB}+(B7%@g>I!kMQ``k0YV_!Yh+N9n#4fxt3 zh7oz9^JtA zfs%R{nJwr40>JhqHQ!NsNJ7{wVkD}N{zh{FW4hFHHkFD{(43gCBA+pGg!a!IZWOex z%wCIX9SY5jcy;A04j!5L+${rH%XJP{1#(?>eIK`W5A8#k8Tcg7A9! zW^}$3Gqe1ae0;iS3SIo@{|jedX^uCQvGlupT3Wj2BYS(sf|ytmp5FffC`>E`PpBpF z-`D?KYN_~M(9dCKxWT{vUI1PvG#~ckL$mi^d%9dVSKLiLKubKmB}D*`Wrhx2q@rg# z;}}|`TGgY(;xINW+Kt(?9}boBx@OV#XQ40C&^W){hIlc4)y~_q=JzWuRsDe~t3c@` zde1i7F57|CuUZR2e&*KgQt5m34}0DodBtV^sRGu|P)`X)!&59-w31Sgu%`@1jd_^F zsf?gppU9wG?}Y#T@Bx&4r9mnB8^L4HBc)A4P_sf(f-VbG#Ol0}c+NuQ3se&8Ly$Iw+|Z&62e*pOv$wpk-+s3oEteyW^mxiILM2A_G93NUCaMXN}8agw|=% zm7m)35G^7P7vCwZ8tPiRm1D-pq?VBOwJ!Lp;$Z{#geU@?Xpo#_c9q>G<6RFken{p_ zjynk^(hzu{cu6Ral%5U}1S>2?QgnYqXxBF!_>S@<@njH<{N=wh!M2_@&EOU2I$yON zKr3~TbrD#qEargAy&3_ zIksRWw!$->P$h`BQ)Xs9o|eE^JXpCf5SVTDkAp&sRs9{e7_r2;e}bDe9r>AquQNlo zVejT++3o-QYkdOp#)3F3vekju*!T4SI0NYKwLa1$mj7q)`A8Qg#R@G(>R)}i+|KV& zU)0L`({k_QU}<6G)wxPr%lMkj<(mBROZ5WfI2}Pwy2jnlt-P8kPq35Cj#VIUC>slt zL4=*Jx}^>;%g?RNP}J-NND7U>3h*{D%UgDM()pRX(zwlT0_b_vb8A)S#5OQTl|BFY zz}W9#X5DIy{Z;~2E-h!^hx6y(4b6pJ<nlbW^?~Q<*)9aSbz1Cv(*tZK48YK2irRFn zPR)()@gXrU1ZA>4^18-tyOVA463ou^@IeJFV~k`%ccZzAt~R~4gO_X9#ev(U!zOt0 zl7nOUH0X?W2!F!?Q2y(>eY|ra3Sr^x^B0}e3d)k*ra_kbpz%^e>^tN=fw(Tps_qjC z+YnTHRS&67QRcZY>c2EfEWi+UVw3fmlkG2<)8c;a?>yy>RYXo2ZNT2<>Zw{ zb==AnfA!sD$^_deReLHUPCY=uLw1<6a@I^myyKon&Iy&aUv;R&l7;InKFMtc7f&qU zJbr+SNcn;L4sY-Ff5Oz&53Vu$7N))*Ut5k?e#MHPnn(>LPwuVcTLUB)nHo2-*g|z! z&0d_#!qBQ!>W~P1@pqtCB1oZ`4s}@bDD4&j+=+D|qvTdI17)Ykaz2$Iexe?;IDiP5 z4=dYQR>)7qt26iW3Yj}~qBtgA!^|pXOUG&-ArbZqnPr2Dx)bgD3){@s;+L}iYGg}{OQ%u4dL&(a1Ev&OXk~r;L!gt>L8T!7-SL6W}WP5%05kSr?e96?}8w z#=Fo1)^lPLlFTA*e*G#eH6LVf*-;`E{@13tN4>|W=~n1KSyw;P2p|GTfO8CE3spJ` zFrsvuFnM?lGg=f);|rGI21bFnL3@7C4gP@GYq?}uI#!;UUoAsvrC8JAYtJ8GOXZoX zYg2_z?^RNR1W4iF6?J=@ckr7slX%3pz{PABQ%3Ups=q-DsSJmGhY~+oKoWHj7pt*9~4YMwgs!VU_wf8)162ONhEW#dLVwcvr z!P8h0F(fRi99<$z$K<7YU81wlA^co?fLe?S7(`qYip@}R`OX=D5{;XD@Fy}>Y^Lf} zdOWQRP>)rPm+xONnd_W)&6VrO{6~coY5ya1oF%!*Q@4Y6;kHK8J*Ps{ugfqLTLkXK zt>?;Hmks3GF*N2tE3L~I&Qh@#PJ3&;R3obrgP!{T_4SoeQAgj}0|N}5GK9pC0#ZZQ zz~HRGLeHnE2w&m2l)U!ZeQG3=rxhACnC7`*YPHA+!B1QzU_%;-#;-Z*0dKu- zj);Na6}e(zF|OU(`&>@&6 z{$1~+sj+A^b1ap?j0(iydb`(gj;;w4Ef$9`V2(lOI_pkTZ?`QjrCYs=(~_sc%*8RQ zo3VE6Q!5(-{EkApUkn;*hRUp+&KLcE(}ZuJQt>qOsJ9 z1>rxtsx4-}vBW0rH0mDUMNKOcZU-E4XKI9`<12D$<_H%Jjzt8VykkmUOTZu}pUxZ5Cz((Yz9e6}rlOWX&Grph6?9a!>x?q$ zs#`F-GM3rk$ar^vPWpl($Jm@t@}y2A?r6sY-lKV>bT;u~Ob&ym7fZ7q)K#>3ZVcj<|3#fbD>scDPe%KAH! zR;>uOea-%vnKO8~5c)KQ8~4I1T8U&=556!w7UaGkYC70-M+ctI^ZRaE_$SS(j;*+o zUc2ans9fMBd7R(PJ56zswFU%&@{{W&rN7KcX47q6h%R1jkod~VaziE=Ee#+e6Y5=A zBH-uis687aSYF>k-i((6s67&Zm42`Lpq<{iG)VVz`TB^^ zAU}lqD03QM3z&xvt+xxSXPve`P7&HwG~~}yS^F~gQTN4nHzk6R`EB9P=L>ebbsv;o zLhQE4Ju$3GgaYPGy~LIcz8|EjIquCt?u`|t2K8Ovi$sUF&851JVq5{K{s(dmzGFwj z>9N4ftrqK^^mRpEw}~Zx6rQ;Cz+RO! z6%nh;fYZXwKQhd#C<|>4L_;cwaSQQ$_D(&$cqV7RlakD*GeIrAgqqqbv*f^shez7x zM6)X<*}-7+qgn0is?A??o@yIBb*$NC!`DbpL;Rvc*CO!jIsc;$z7&#Y9By-K z{cAv3-HFFG1yb};^2!Qy@NE))UCM)!88LHv~Egob_WDg9T-E$?gZe@#7Z`w1u7K?nRI8&atX3$LN z3aR_FmCmk2NPe4L$@g0mNnGqt>f@?SdYlgESUm31r3icYZH+v!LakhXr1Sfs?h7@k z+0v)^tn;OKU;M{@^kT+lbzeuX@ENpeEUQt>)Arj9pjp_MKU&*pwoRr8aCypPZ)@T-r^VW1Ec-!%W7}{f;5kak4|b(+VD9Y zz-SqjL~Ool#rLEKU74)6+_WI%=|4I!`l?URQ-lN@e@i}q7eN6myL3hU`|+L>voz@& z5%RQbUYjeani%}EJBb)<_n%;^hu#l*uZSj zBRU$7YZprMN8RZ?1EcvlA3uWpUW-twqRP~aFkq)iPC4dpU~u{RO8sHwsFC|v={my` zpOO84JDz*OSvzqB4cnMch^}bAtV_+V*Bck>o0;z@%p4cOo_~%%3uqVtL?Am)0H6RH zLU}aD0AEaacfk~X`?TwL`Cpu1kh*tnixxbn_riwBc#tjH&lVoXyZ)g|rXp22`EFzp zzIJkz$COQU!ySEmHpN`qaDLw7@Qwcu1z>e!WRuGs7kqsb)VUmaY&iYu)7WBLYH-hu z(cMd*Lb+S7!mJ^=+l%M5S@_;%jrdtFujRV?N3H*VV@xzkY9436f?&G?yuAcvi3&R9qx-bD%mlv-8aYa)29}v4^-H)_AAc6uMX#sAG zzs-Bj=70L^Pj*aQx%2h;&n7!POLkICwnOmV)0YGe;|lf`_L=03ucUk;>5#l*I4(U` zW<*|1K=$>ptIr4` zAb4@nb!1g4cD3n~hm31ayAOa?mDKEp$LcwjXa>U9Y@hkqjK6tM!|2pl*Z|A)7>o$} zp5cJ!JKbNFq%#!CP}4E3R+Nm^b^1B2KRL8E%~`%yxE1L{rdtguD=H$?e!D9q7Uw`+ z*zJv*-k<|^_|7+I^-S+O_+;9@Y?GQE$yNh*YO>=bJ4HS0$^Y$&Jp^#~ct_0XPo5Mg)_S|m`^^?yFv^*D&aU_gigu3M zDW#AJ!Zw{>_FWHw1w1VuLYe0JQ@*z{ZLLxBVo*n!c6xuh0+)}7bg7t7^J-r!C^pj7l``Is)?j|vG(MnE{ypq)lO|?zl)E_W z+e#Q3^^Odzz_ka)(VQp4PdVp;sjSE&?K?Y=rJ~sQVZIMwx4y)%3!~M7kjbdkINHc= zyY8aY3D`>QxroghoWQS?A8l-swDsN(S|8J}4bpZ2-CSZ%SK(4IZ{N{+b$8kYc1v6Y zOkNX`N~jN9vgE*@W@30LP^PLh4O|)_disyi)-UK8upF4myT5**ecR3cnbxZNYcZ{4 zH+$_lXT3QyG51b_yT8u_O}L+_sv~o}9RHCcU2q5ZqrMin0$CBlNAh5Lt$UDIx+()c zjBqUmzLsi3H|F%Pd64}QM0X{oYJN8#6OU(Rlujf#66#A;_Hg>|#cbRzFeQm;NVeWE zG3{3wnP-J-h-|tl^v`T+{SXIju!B5fq4+S{{zN57_gf3YA}Y_2`_n1`YLF+Bz@Mo0 zUTyMy7RQJkw1mHbnh?S3X@${ZcP!!13U&hn8^%9x@s}Lq%?d>Dy4xPmigH>`3{fpT zka$b;f_n%pjGU}oVmN4HNQL}s!#2WswuEhj_jrlb2-gwCXoj8AMh!DG13yGjIbnHS zZxA++(>{3>C@2T15&Bmoz$T{goGc3OfyNJFt0ozE24Ifq+!h z#5&gayIIarVv|;jQNmfI^adz1n`j5@v0DWX+Mf*Af&9sas1V~2?5Wa_NJO2LaOEKh zdabte_0?X{NIdmop4Kve5j_|IWoBKZbxE~$+SXGwm$aC>FG1%d#JP-S!0;>S~hC(R+Jz&Gx zQx$NhMQwuD$xd*_XepyuLhivz^5Oz^hGF4?CADX({<&0oMbZ-)ZmXga5pG-P1;T<- zdM>-z1S3k<3C02K$Jp&66H;hF649$i>K%knH-tDsh3^Mm*+QAH`MPDUv(s3gKd}~_ zc)0`Hz)h3hGR79O<=HF2QV{=(P@qIcIXyXHnu+KYQ>QkcGD=Dj!jeNu;T2WbVNvEhIBq#kCH?I&gElsxCQlcy#~E|64)L4>H3z%U z_qui}sPKmW-w@q>eHMDDfDEU3f03oE&%vXR!^+O1z|PEiLEaacg3j>hO8sXsMr9aN zf8^4W${aYma*^ZoyA==i?Op&YxM~DmbVR1YWBUVWw{q*Rg8;^*CZxs4sjqu2Y;*i* zQZtX2I&6xZp4&)-Jtzi7c8ccAUYo~q!?)-74K`}2H_@&^Yic{|GRx#=O%&@6^m=D^ z*^nSO7T!5z)08Q^ZdBh|j@yQ7Y##Ft$e!VE^yHJ0fP~5dh&o~8G zL;!EfWU92SZXD#21nSOTBIZL`#^gBydTz02>_*BP%Kh=O)(f!?7HW_tQ<3?R%y((N z?zJamgyp!D<8Hd=_5RAXlHSM;%SiPV74N4BN7qT*X7W7_H##${hfCO6ONF3Fyh&v2 ztdPrzp`TbGRvkS4VQJXICC+I)oVN=yFn~BTQB@A(Vqm^X+Gi?1Ti0RvoEt2&8cRGI zyLg6}senPED$ra+quSao^Dl4BYj=e9e4ZQ3lJLAw5A23-Hv7-GS)kLfk11i%*<)XS zx8#)Y5wE~TDVc6?3%OA~EUkTQYeiTepKyP{<(Lzk-aubjxKJ3)6I#37>7b}ti>mB}IO9o~$ za1=|b=qA}vq1`d%#*-1xFDfc{60)rrtXQ&mCG=TX35X2uG3U(zl>>@sX%Xa%BOzI* z5|E}Y$jp-nzQK!C^W|;(r%DLepT+@H2`Gge{2GnRa;+^{vZcR@BP)LuH5cHY7K74% z4N=O8;7q)e<=v2!&s42el{-`FvE_+|_T2Va2kG;%jVV$IG-d4wZ32NBH1W=%pQ$Ld zLRYE2Ccu(#SU7&4S9=GWQ3)`_+mGY4aPV>7{1GTDdi6K#h%!Mr=MxkVde$pTAgd*% zajCpNKD5CjZ`c?7G1zKy>$ppXVi3R5S^9J zx3H8f4$L(d+f;gV<3NiZLiZrNzZjvPNQhkLS?3%+Jg(+?%c~~ccE#JD%-av3%IEOR z^K)oqetb^wq0)6x=vD{f14I9Q?BLY9D|C@RBWTcyO;r!u4a%nw`1`1}mN$*xL@-AsB(JizX>^PI14$IUp!JBztgtYRx{ANHXaC}YUiPY-?QJ^k&>A@FZqUjOnC)Q zi3Ch}5w`AD;&pS@eiPPfmVD1KV{OhUV+E$Y!~~Wpw*9tZ z=2tuGu0~EL#()_xvC=IJoil(+J3?J0ahk2&X~Y-10-C6u=U2)b-CIX)KX=V-jLz*> zo=Y-aU93X)QLw!W$LN5USiy~CZGSAwd|~>LD$m|NXSDsQ_|fK zs)}VF_R_PI_#nyzbp;32#HSBVW02(y&O*!?$uW~gAwZW_i1T{|I_>=OnUzm1<9q=~ z;d@QaH#AS%+_hbWfTnL(RjngooY~ZtME1B}(?cndU|KK@I;r0>$e2VOlzf0I1`wJE zybq&7a(ghA;XN+9<}t&a4Ile4TG7{;?%+UW1~FlB$n1HpsZ&ClpkvkL`~A#5q(7&u zHzVJO2-w2PX>4k*B7`iiWrE0uno#Jwf*+aWc}Aa)(-u@2GO3m zy@&a}^R^Z@9EgD{Xtmv!@WB$OGUyNAVX+dQ_@w()^QWeoG^d_{yA~{qmcrlvf}(k& z-kET}GN|gHA{9huPR#KoR!#j>;dX3N&1e2p7y~$T`~DF>35R&dj48dGy5q^zRP*!bjKwnU;_6vy{(e+Ff-TF)u8p zhW>Z*^0_@oU}*qfRmoSXeVpQR?1AUk5(yD{p@r@+2fCj7L!3KJ?fR_QDCtDN*l47tizJvyL?{=3KEms&Hig;LE;f((Y`MU_XQ=i_YT17y?Uxqk7 zqBv)_xFh+v?|$hd z%YDIcHxrb*#J==*Z1sFF9mJ64myzJdAnHG8jEGf{(WLt+jDlw1D%SoBlWgUFCypZ# zaOg=}gK8@EDuggR_8&lpQ2=qmJX%sl;BB;q*uGF5wnX-c#N^>Yb1i{{`mw~`q35kP zm2q!%G^aQwBX$~7zfZqEqb1#aw3u@Y54Px%O;^@A*)!OCr*{kqf%WWVd zIG+WL`@M{Hf|bvV@d7?*a<{qd*WqxP9b zJt)~tq|4OU!-m7LBss^5mM*fO&f!Ouam|*s*@Db(E?#q988@o+22W{fRBAon=Al2E zSv;W8INjEoCR#KqJ72E#q;9*wAGUXo#CcTf(ZL#w(uRc{sVazw%-)?v(7)0=T?(gO6Q-zjH z@V{=R)q8P>Lq+0I8j~ht1j@CdnWjKp03_u{H=>e<6xqUpK6|m-l3&4&#qA3rgq++{HmK>9)r|h zC&)ZCz01}#HG}-)+;X+a{NrZ@`o-`(tssRw6TQov?k(?3?h=2qJb%3@M|}rDyW2Pe z2NAp4V2!*c?tlX#o?Wb=7ca{&V%GA{GZFBO?Ka+=nX?; z6NrRC%V?@X#YXQdTLJe~vj*APaMO^J(8OezDH_y7J9 z;UD}WE>1Hp{l!|%gp-%||6l(7JLmAsxfYzO*Q*raxAB}y=zkly{^$K)@x*ZPf6N;& zYU{*WGB6rXtl|3PL5FXuoF4FWJYMqpls3REYHqvkIj5va4QtJ^&vs54>2oabFLV8F` z`CV?kfr)Un$3_8^_}D5e1uBz2CA9tERv-LZ127y>wg%b=5hsl0S8aYTe*=R7!SXu| z*4K*>+!LY>dDKsbFvPzP%`ZW{NAeEr!ZNi2{keiJmJ9|g1)Li`#{y6>AnD0*3V9f7 zM5Tk&@-nv}&dhK>PCeeU{n_6RnL)vp?vNMZ5T#b;Adm@}p>)B~tZidP9ao)*c$|mp z*_G|3wPxb?&CKZGHfnQke*wUpw-@6jQ+~}2vi6I#5bUr0A6ZYswu$0jgL{wUJ=mRK zTB<$VldB-A1F-KZv?V>;iRk-TE+=B&!hjxB^>(x>7~`3?>zVKBs-SOW4!hppZjPK4 zSC_CBWpxPahZb(4^_VQ-46ND$-u8awoiNoX%Z#b9NVF9>Og&s8f86OMf`b5LB%Fy` zjnvF?(+0E(T-8e(8B)26lZ~C^`N5R#2|$>$XZ%1itHsEeAws56Ze~rDC7!bYlh!<_ zb}|lkMnR8Fl^*#>m4NyYRfJ&HuZ#5Ld-dX$}h!faAW#+KKuKfAtQ-GoTyEyw$s?KQ~F` zw&fhe`5k9&PG=E>c;iMq%DQb%I5}mPufV;BF#&(9rD+X}!yfL*5y-g5ycf>)k|FNI zbxc_;XTf0A8olA6T-dd$H_o`id}e$M4jW8Xs=!9NyCH8>{L{(aL)lb4S9)7O?K z+s;obni}`i)W;m^^x7YhGHV9FM+8&N4HLet5YH%>-p#GJ&2kBc1Fh-hkFXw85lvfO-ZTGO!SkK5H9>k>FPow_`e|_W3-g2oNFmSLY%PRD(TE>!` znd}a|HfI;BxV8hJ>gX)Fc1#tg$*Q#lHhwOe=inZ|Tkh4DD9f1yGonq!^cvbUhc}{X zLujh9@tC;$c-{;&xX&Byn6zTWo2IOfN+$+Nd*!aq%{1O)b7X*gpCffCQHCk8HZIS1 zmXf*ve*~v`mZUu*6$W5WP(doDjM$?BkyYWX`O#JWM4vRLOk#cWG!~D@ivi{3uJ9T> z2&Vb2i6Fu&%I&n8HTjD*Y>D+tGimaOv=~6%rv-W!f-|jG)`H|^bEdWCWKZW`4avKj zt}WsymRDxV^Iyw|0pR7XP%ph>+UqqXR=z~+M`cma>lsPKg_dCpY@9$n9xXAt%j)DIJFQvH41D|%yV+mU`2x-lRp(7 ze{BtPEzKt_5{zaIYGYl&Kb;%;8X^T$7pv}W8I67I)wIYyr`?amcYx~zzy_F=d-#$x zt(N2&yQV|7JWj7dMlQ6*$9#+yMTEc6IbQt%tlA<5WRp3sqb=C*TwAZCqerw<@zy!U z^mC`JI{zRT_lT__zLR&6iZdsGbWfJNe@m1K;`7m}bwG~E_s+1p4s|DKEKy?2lv|-< zRWbEx`|xr*JlG5!PCVv9dgqwUOYM)3!ZGAhNi}?EvoiOZ^cWeXfBx}n zT8}27!A=Y$g<+n<2tQHg)zIT9OSk@5c-Ff(%|}_&XGQ32d;Hi&E(OjVVwrG03A*;h z|LBrir~Up|4k7;;NyS6tdm!WD^|78E@G3BZHVhY2sAYTnweECWmWrd9Em8!o%Q=^3 z`>ixxa7_j82RshUO2$o%>!WcofBCf;+3U$E>taTCy`D5MbGv#&d}H)_R&Reud#hrq zo4=KBd^6iv^YCi4_*7NQPb17N=aRM<=Uch!J9Zk3V4{^62-3l1EgXp3W|sK=AyKEqWo!8R=U~J@NU$tm#Q`f;G}I;4AYIW7^D`Gs3vxe=|}4lS$Ka zAd=>|@eM#TXz!5_q_HWJ1{+dv^^D73E?KPsMDf~ik5t*y8d`vsI$xjMd~d)vQKLut z1T}7gZEA%REe;#$U&(!isK5O~@PGVI@H3A75`Oe}pCE|QOxcki>TL{64&Fhu(uKpZbB;eaPdeBme@*0vL?)4J-R z5be4HqUsr%)gf=rt?J>%y9=ev4K-vqcVs&u1=HTPVKmv!3H9loO|NGl^f*-QG2YW=E^7h?Rq}YjL=xWvCXRI_skD2CbrWO1e0`zz$0vz@=2yU5a?~4HPCf-7T z=ObApO8xhXH}G|mfoM1co_IY8ktO-rj%x1qqwHdQP)p87>q8HaL@^ z85V!LjwH7+zpvO(3a-WX0~joDqq!B}#DJm9c4`3z?7;sYxXEG_t4MZF&z^$C?DVk7 zV!dCadi&!|z5Vt@wa@$SUw-+}{w;4gnBd-i|JN72|DfLVTk@N-`7K7j8N2`TpSQo? zlnP2IYm{Tj7~$AF#`f>!Gvs%Z z%J@)bF#CVr!RlVO(Wyal?`!Pe9vqeegZ(Ju2)aAWP{sw*W@!J1`iUct*V~_^_pd&? zvO?l3lqXihZ1{e8C$vAW39`1fzr(r+M}e=tq4=%}PRrjoAN>FR&)@$tkuBKG#EgGr zGxq&!#b??w8D4E(rvc;yVmM+JiVfr*PAsY zXdK;T-Hue`;M903)!BaeaQaQ_Eqi~j<4TT=-JH=heSNchzJJ{(Q>U2T7cINC5qAC6 zcpP801@zkgS6v)tdbS-sfO0T{i*;YNBGJGM12og{q@tUnIsv<`8*joutB zW>+`X>OToSf-4lXaw-`dLR5dUikX>RnK6n2Xr#MMXQB#joky76Iv1J<(3hRH1&g;; z3E;*J^*uw#Wi#%uu1K5orZq`uw{IPHCdM1XrjaUNsE(KhHmtZy93PqE0Vnsqnezl< zQ$7oZOhU31LX^F8D`W2X{tviE;MUZ&64LSB*$$Wq+2hsOxWhrH;9P%OxskEVsAqft zZ^;?Qm2%U4q-mNq0{l18UlBXxO$Vek8UUAyMo>cW=mTE{ekpI3^*N;haexT^R%LYW zZ^*v5*2qtV>=TpM)lLm7%?>)ajNf$!v0U|kPu9bCa3_wLOxL_nHrAP-9(}sUnJ`>tQIE1LSa8Ra-pQ4gg9Jp@S6qwewM*3nZ;6q&2U zbWvkal#O7zPs--Rz@pA+BPw=!^1*!{dRho}@5mqhmquPOBo~OCu7*$$m;Z&LK-l*nR zcRkoboiy9eN*SF`nHNWx4-R>m83W_?#4%<=wP6X_vBI;A7>kxtlD@mRcK9SQm zDSKr0g(82$*%lZZ-GmB1dU9MvlD<~VD3n!F*91Lc#QBfIBA?^tOyX%<3@axmHHH!R z`s6}1PD2r@7*K+0ShLI~)G^nx2{d_CsqMuf!AO*c!JbK8h2bgJ!uGks2(zZgIL1di zDZC001W<$1TD3}wpGNPBu=}TrmejQ1;Fj#PmT`YEd=pxu4QK|eh#Wi}y&)Jko2l}P z8A6gOjFhbE%kq@i5K7lHu)X4_!E$HuN8dAI8D<{oDnkkaGeJhweFvJsQ@aCiGk;RE zrseIO%S|Wr?dEmr`QHIs-KM~tL@4eA*Ay*Dqn$X9ejjrr z)&_r;LqwAab0+TSDx77qgLMYd)U7W9g7uKBn^7=q04Gwnxb%o78%z$;Z5#Q=YJASc-M3x9774G-2y@I-jAns zb_#^V3t-PO{;)9lkm?B#q|3C>WqOiw_B$@)tc3d)Huce!9uFh?#+O8Nc?+sr($Te` z95+Qq@I<<4?n2FvB+ln^z8D?ytCPtzD1VKvOPboa1#dY`!Qq=gu1~JHw4;c&cX=G; zp0Ppq%Ni>iLs~A>T)qmW26rkuQCSBgxa~lgvP6TuE;3hGa}l@f&%=4k$=C; zq!37y28fZ2I@K2#8p^VTTB3;qiY1mnMbpc&4-_z9Bxade@UR<-2o61t7+Fk)7z0(s zJ!j^5tVpiy7M=N|*MteTu_nuV8^$D7?+}?-G%J0`XHto2he?QjB{Px4-ngPl4YuWpVYGOXO)guUaDN+^X5mge2LxaA~^61|GCPm`uZ z*660DiG=C4uD#42G0qObL7M6~e13Q%FDycvC-eLYj$O%%Q++gcs((-j=OQFQg zI*5m1EK2X(8gelAk>aXjdtN>Z`^BVJb$)lUM`p~(czQSiS~lsNx{B z=A2M3!a+M9i5#)PQL|AL%|?Wd(+&Y80v6Qv($&J132mS7?p8$9X48i9Cf)UVp@S21 zIaBJ^`#;5_s%a+-x_U8}hj_Gk7T#DAlhJR}7nzg%+&1&u@(^uwW zta@LE7ZKTJUy)6zO@}m|;TTUS$dHO;OnANOw$_@o{g}tLkWa~NVDgH!nhp;{oJtfn zkKui;15n5Vb?Z@O)}qEbwytbk)BB=%|_kbl)v2I;CIfQ(2Fe3*Kpx;KD{Q00@udP@>)ZinI_wap_RGT#Vah5#(%pw8+ltI4ZO+E-6^-YKS54&)GZ-UwOlwjNNz} zJb%HqQmZ`sNb}eaaW4As?2px9bII^t^tA`m%v&0LBInH+Dl+d-#?g?FCa=Pzq30jY z7VCipoaa?4oSnBk!R#XpSUn$)r8zpQ@r>Ls@}h9XzE}#2{*k=g+SWp|xgMTwlIVyXWp6m($XIobjBrjl_TYBml=gXdP z=4r|MkjEF1uoa~oT7vr_q>l(KA_;`t6CbUNLsMRFmpZDKnrt>7jXX8o@(SF#JFyEF zZ}Tah`Mh_Y85{4*`-BC95ZQ9HtZo`2d+ z08S0t9?w4T(!N(yBfMu7tqvLsW>*wWY706(4NeONl{szOR_0<+kR)Cieu_>_(W)|6 z6Tiw_t<_cJsi_=TCkWj0S7veI6Hn}ytV>N^-Vt!qqAbw6_&(K>lv!?WJ|T|TiGh!l zm1)`)DMQ*q&@bIP0oX{)g12gLlYiUt>$S5JxKDi>60PK!Oa#3ThdUqAZ<|g^D0R}| zLxDS&UdV;rR~5p(vypX4|K3;K=CsG7`%&yfZn8egoY(nRMD<~dD)3VRYw7bMH1%EEl%r&cCKzk=U(R=u1k{j1~C7kR@ zRuo{sU3?;Z;v`WDw=pHPZhux<6;T7NN6pK%ch%`!rXQNOqN2-k0wOqRvMUkLUg;Oj@m)Rjlvo>@e$Aez}atnnQ zts_1!f+l-3?n?8APk+LyV?2&wWeh$35eYn>&RRPlTj>{mEGc)-gCXh#^Z9mQY?czL zbJ%ikn|K=6vKF-k7k9XNEeqGZsU3Z5sc$1*~ENdH3KCYH`RYw233 zu?%4SbjvN>LHSCbXus6SoVKA&$2~F95*gsYk9vY}Tz{WCSsw|tpFMj5uU^QstqADy zruAzFLd2yCs~#CUHS(f!Xg_i3$NKEjd_n|AoF<#C{nXhw0l2u+zzp|M4eIIQowVBM z&GdUY@lM*39c_2gp5M>gvMl1ZGbsQ2;bc0U_n;eQ-)n!+P9Ljp@~|DWH2B56zwor& z`)fR?#(!Y1UDk+;A!z!n4t(WeTCL2MItvHZ>`!^}oS2h3nqZM8d|-=E=5yV5*2yTka~s#6I4AJ%aQO`q_|zbQ7SlAyz!46uv0cM(QMu( z@qf}eE1KvxtGsyQoE1&7n+@ibHB#I+zvh60&1bs{NFFz@&jnlQEhsne&6qDrSMx<# zbo*s$NXXm^!#K_vmY&FIz86MTjb#5~uXtd4XS$7m3_1MORr9+VS~)-Cwf=C&^HdVA zSNUQXXpNt4hIIVE6g!(8>#ongYeKz?S|3khD6*-5y&9}LsRoY9G2o|kpzMOlD*C@ zunQP*4!i64&>FSnf#exsW|Y|Z^?8p&OP00LaP4j^AT_&Z*u}?UvFeemaV9FGoGB`x zutr(qP+( zqf0IZbQ@i9=zEaFI-){$1eH|4>qjnsW)&^*#G)eKa6;u6)Df#IqOx5IDtTO7 z!q`NMK|?c10NkadQYyflvP#9XPEpyQqJwI(BaF^yyF{xf-!|f;Vz?N-obKVvAjcTm_&Rx;f}-Z9k9b*X@igq zlksQ+?_$)5mNy|E{qTc2ex;6oTK}?E$IsPw+nY1~jf>rKz0#-JYx}+W@yDa@e)UQ4 zpMEvQobod8vf$;CmkVAtysUY-;bq0k`S(X1t+`nwP+gsV2+iooS+IwC7lTkmb;}^@Fdc&qz<(H4wqdI;$T;Td_z1oed-4=eu z?yLShZr3-P#mJA${-b}6=gZ-A{Q(mBNi0!w(&S)uE|3dZ8wgRfXTH$dxrg9i|NakN z&<0kOo!17Iv%0yuxp|3BkvuJv=Uc4H2 z=)v*J=P#h)@xwuVXL+FS9KKH9$0w`Rnlg+1r2p47*6@L$W?%Y$R)$u_R!S>VD|0LN z{bPvPmrY)1@!=nIec?}wyV$oSgtPB@#%VVK5kx9jD2(bx8uJbKYLAC<_)c9L9^q`!g!?U zG#tB?pe-N8Y72O8j!%?&;Eb9Zs_yi@seUz#l667ANIq*0Loik&QmYh-hL!wx7CROvvXu(uR?AHMy`7jta0~jmXVwQt1Y6l;ZT+|VNe&jG1KLZ%!bO1d7vDMIv z^*Tt8Uc!V>KoT^F5y%=8LQ)ot_JP=}j^+u)+ygYJ-P}UTfI{vL#c)nbE?Ok?LYl#P zM6&ik01MJ!TuKs5xyN|ogjkxVksvxoE>N;2MU@z}fX6-QYUa?151J0oX>w=@9%hpc zs>IFVX#|shT0*SD!(b)e!eDF%m^t)fjYgovl0|d1BDUykr31?hjwYhS(v3`DZ?`7t z+@+W~Tn*NjI+NK&sK%tqu8NVKdF^I$H8DAzK?}g&Fu78N*pJA~fk=!lRY^u8ngby| zFR>Srp92!0WW%L+fnWA`E`ZpJXckKXl`wT{0>g%XND)KQC3Pz)&M?!!Ck%M2EhK(K z2)^MvCfW=UA{xX^?vKDj2ZZuyNlFhyh#9<3C|GTB2Lq&7IBK9hbkB#B;%AxaAr)PB z=2Fz$B?$#A;^ z=5RTGAz}SE|X#3bps*vA_~(7R1dnrgB{Ox z2DrTkolfyUKn>GRFAtKD>rsIrx$xi^B_EC#VUFMhBB*mcNPs8d8J2@dJJ$imO+P@S z?6e)h)?D)6-EQ@=36Xn1fakHwd>djJeh;%IFCgq8YdXzGB?i=vO2KL5H7hH z$paP#bK&N+<6KHTikZQ=5XAn#HR~)qWwAQA4lFaQrntAoqgO|#!qa{5ik>af6D>1< z$>0s1a|n~0hp(U&PwtT3f=M%gNr<_BJe?0@S^$$H7)0m*lV<=U+;8KysMTT#j`XHS zGi7?;ixsX8ba`-fi~%-Uus?Ue_nyw671Hp`wF}lT2+!7+uC3A2Ief3Rf+1lJh^=;G z9gH`+4lpzLUTXq))85rYVQNDJ*OU%0bI?qz<7(EANr+0!%AvA;+)%xDR^$_wP4L8jDHzRM2(EUMlzJ#_(j#GFvD}UNe0;n7%kV7*{UwxA zv^C`xO0Xd2AQYWY&L)Hs;PiO-dke*5as}55WicTXhRlNXY;vGmDb>|NhUM_2o>@AN zLs`AuO^Cw@93NHCa5#{hQ1%%E_DLM);{tPJGh8kI7|$<;_v56f;B-uXPy+rJYDyxO z+i+D<mwz6A#34n4U3xZJF-u5PZ+hRx>V zl(Wk~Q~3@M_etPL4g=cmhRx+_+->nNsa) zKt6)S*R#vbrZQQVo|KQK+#}q18B(LyDc^yALg-KMiyfdyKQMsKeq3+YlNuGc8OT1!Vix}TL+4n3M566uc?Ekb zA1;Q?asVQCy;-l{PD-K!R?3({|Wbwa&D7h8503Dmyu5eDw8Bm8Gnx? zxpBVFuc+fLjLGHu0kj*K+L|_?i(zPQvQ8ExK=2yyNq=7?gAt4%nOW5X*oQ_}X7Ujv zgYozxNOk+$P2K+Oi|YUHzkT`TL;G7kaxlT&e*5beT|TIrz9oMsn{P4t!`SlW_uHS| zl(OHI^7`GR@;e&%Z%z5F#_yn%GJlWvuO^!EM*mvgnDXT7ck|K9ls|KavabHNr35x$ zK5FsUpIQU8Sc0O^1vXgUxCcI24NZFob+D`UPAmNpkeJ$f=&kum$OC@62M{*((!YlM zZXz4H*PXV2L)Q5A!Ry;Qyscw#3Hx`3Pfh(^`>ErM0pEt)CY;SjEz`#Iz<)8m|M|B+ zlywYxw~j8@!$vbNWThmkPLY9L>u+PnbE7XeYM_T}PAMIkn6ZO892?)iTBrKDw}s5T zn@9a(`_#4x%k_;OL%tf6_U2F_&V5$m%cOf)1o+>2`>2aLo&zl9)u43tM<|_7JyhCk zqzB9-MSbEH2t6RT)D{nuj_j_MLs=;;=zG_o& z2hK%;=1ps;$!NyP+wrzcs~6KZI2B4XuDOrBSH(npTY9OJK68%Ohc(2Srf-(on7c#e z%Is}(m@(#M#;l!cS5hjGZLki9)uk6QwF|rTH_9J+qV1=D|G8JO+kYzB9;$GYsPdo6 zE3B3GwZf6o)Y0F6zNAg(Blsw*+^>5v@rc@<^s*n0RfkJ@8IJz>YTpzQb6D@^H7&cM z?`L-lM~*gmSt}me)LQPycE}L(lHjpL!evdB6qCNmEL*g`wT+XBKYe(6MG_L@^mYR> zU+O&yhU^+4+b#-RSAUJIpF4^Ls5wdw_66#Q3e-S`dhenL1&TE|G7zcj?rWMS>AqJ{ z6_bK)bxGf}rxShCznbsRhraU}v8dV~L%oyUq`8w)hUv__l@LZB&IXdg28G(_B6h`1 zlU0avUZH(*A78neF9bDms??6zF{zEFLme)(vzs*d!liJ3!+)i)YlS%lu|A;H3TDBTS3lu_o3W|?X_J|m78?w zE9&&npt#{kuYp|ukmei_nMt}#U4*O;?-E%&s7i9BIxXW!eYc^8vpC0jnz>8EB)Fp# zn)?oVSX^y)lYd?N?$L;F*TT+}2@5vPE#vy7&H6R!Q|{`MCasM&g9Pm3M(Gj_YW4D; zI0(3-&Oq1eUqLi|bm4X9jGQNtij3G-b6SGISnGoHmP}+r!ktb6I$`Pf#uz@bO|Z8X zcKj0a;j<+(wI1bHWkq1rbjkd2=q(x=);w>Y>PS|m5kEF`*VWC+&8vG}VGIG+308*Q zs$n14ZUKxfj-|M-fsD8J9D*-iS{hrnFXY+m7AujN9&B6`A^ zt}|;vMf7&-o^+4Fl$=GHNLF!L<4ythEgPj|41Yd`Eu!BhlZ;BE(nXIK7Z_R>o??5$ z95vhrC^R@(XqAjki0$rc8S_ShVw%|fnxEMR!Pz64$l(gUO-+t3&UiCzbJ$2(Xrnm< z?H9s8s5u(2;?7G(RY!GPvwl#E} z1p@(XxuZ_eZ!pWYD?;e}0KWiDLVQx1)6g#NwAo4tY(X19(&$7Z%XYokHcSXi#XzfL z*UyGmmsijl8+DTyAx>gfjOohLcP^Aw5r2#GlfFbCiXU)9Z)BB!y@V5-FP&H`tJq5{ z!G%&(yP0dMn#H|LUf_%cg)sK)juCY}l8#$guelqDakYu0eTH8Vb?#-iwPP5qpvh;b zPE|suSA&nBDj(=Lo zp?o}1D~N{)GMUyZYqP0lvouolR{fM?syY^Y5l90bW{q_N|x0`*a-j5mvy zu=7KBfT1Z1?P!Ru&khfDFoD|1K-Os!+UgLPVmNj|1I@fFSI0Y$s3{URvj@~|yY4Y8 zCmc3cNy9{d1)|Ag>V@I&)5`l)h~x@xzhwu z7sqx#E}q~e@2|{X<7W$g5GWW#ex6}##1psL7aC;otr2lz(JP{L#E?99N_I{bP%l=# zRk~i|vwiGiJaVLcTvfO2s=HVRGJ4<<1pw1irA8B>+H4k&n}^zTx?xsmmV&lohms(vt;Hd6O8T3OoRzT7L-T| zwt=Vwil)SHA|Vg9jP z^KfXANa&#qhc9QuP?T}F2~713lxeq`-W@885YP-fSdUNiNkB5_zBJokV|ZT%Gixg+ z{up*Zwwiz#$-?sKwE<%N=iY25Nmy5&IT|FR5VN;bX9npkq0$RrMSs{st60%T5lM%k zJE3oBu-6!r70B$E#Kvy{*CT_~vRij&4y_1o6VT#7bH3WPq&$XXb$sL57h{$%xPx

MBrb|dvzWo~fbmo}?9ouf>hic3paKUozdPVMcU-hg9hCx#G-btht3Rw-zC5`Q$UV4?QpmA!tq>d>CxH){c`_LXfKT1rfm{JbNQe`()!Rj2eW zp@I1QOtWR|Z7Y(cYRrhh;SOJWF*5n!p=>KN_s zOo74I4L>nzOZy^LjatM;X3>xF=Etm^Zcc!jPct=Vy0%kqcDnpo?8>Wf6hDi0;?Gk}L}F}*7MphKD@fFFf#EBxB8 zCe0cRki+}1g#|BkJd#x;g)4woIjQ{X*+gP8*4Zc)O#&_clipZ1Cp?CU-I1ZUX*Qk$ z;xu?}vntQCc0VQ_S7g!Bw9T;+bh9wiq?h~{lRH@<0aueB<_-aVaYutb7)>i4qQFmJXq@UvLg+Y6dRFFBF}5!or3S9E?pXD(&5L62V@(Z zFK1REk11UcB(6xH!7R-><5d7fHzk^hY@m%2nbSXppGh{z=|LK#giO!zWbmm8!{`}u zGUMPJ;fRUlcSN^D9u@^Zv43B5JLe(#Q(G|l*%pjv;&>hR6rI^EvJQu5=QCcg7hKaY zm^p{G%|3f>Sk)oyAPA>;$_2E{2Mga@_L~ZyqR+8hS3I250wBimRADs(E6@*@*gG1} zp~xY5q2z3a%v;4NKWD5>{RNg-%aF?_heDikM;HePAgQA^=eof#rhm&VQ{X;p#6lH0 z3inBC+9~@&+IHim28iNWy7y1zbb(n>Db7}u8KGD1w2-^eEpBLkJwlV8M)Qh(Zs|J| z|Cv{Jc;3RqZwBMyyhU>b14hGPz-W2MqFOmZcsJ964BM@}3=Ll5ACWt9{2(Y0B;7oQ z*haGhpQDinN3SB%h4w?GuuSkv4&#VaS85{W6oMp$xa2z>n}6v^3nG{uDC+ezu52M)6lezE?pD)>BPq*mH4#=% zuYpNRN~`(|PJeV}_oc<|do|f_K5QR!o#&Bq$ncjBr*B#x+54Kt zxEzYK#ra|9C?S#;zP*1fWVGPN9kYert!9%-(bfAVz}Rf^dcLv{YBdK>@)HjNh`_`1<+n_lGDo*g3+&yY~#SP51lwZ1hlSPUB86sFv~uz&eVexD(r5{ zc)?yQ72q%kUIB!y=XjW6qStKK7_GD%wiUE0{Nln~g9)6=gVGlC|5W=j?FvrEe0$*l zLVp-XrNHa9hIv&dS-8#~$*kj z#E2Ve%#<3tOW}a4U-Xkr>!gmS)i=ea*CKCdQR2>HK#b>iIDU#0%HTaM!jhlkuss9O zHE5m!7mj0&@B}mOcOa2)jg9O;-d%uK6@TT^1D5^V?|gH>hp5TV)+OflD4B!@LuuO6 zKs-4l9L@{pX|U+Tv)gsk?npr-3`NJ|r%YXLj|QQ05Wn?dkg-+It=kqZfphD_oN6om z#EYU~0b4`k{P*?AERp-2C(Y54vfPy8Ez<&OFJ#~B2-l}+Sy zjoon?@A1&Pn-Q_NSSnGycp)Ry9U*YNgqPJ1t$J%nta?;0nk0sj7eroHtA9U8+YS9f zLF=Fo75pwC+a2eH7wpz6|Qjlm^K=ks#!TV+Q?Sd} zSHUjB1CVquNlC=CiFQ5;VRy`MC(MZ6L7e6i;%uWOh|@fUIL!iaE|)1mnGSL87F6fM z81u>{N*CzoQ-f9&Q!^1}{A(12fBA4`YoOw$leJw7$i27QSjxg!!+*lJ9u}tJW}q89 zPADKu{rl;pvOvt4%^D74<4n{3dciq@2bZ7Kp3%MHl8S@Lj!qU{Ybjn5{h|3@$=)ko zWcIC(GvJrS;3m3xOdhXZ>2+2X)*pL2CFR5J)Ag=x5L60!xj9QuqHA{lF@xn&;OMf=Xz_6Q>N@vAmPB5UM+}ANTW`9gD<^-`*$HRw6n-lT4?Y{r^ z<$q^!kcxO${`OzLfBDm&%lp5Szdzj6VRO3uqm}%<*q!PqjhEm5ef#5=|A5QJi$&v$ z!_k8JW3%LXH?_Y-cMJxg%U^@N)pPNxs#8{_a7zles1HA`iGLzsf}y_Rredp@J7d+` z*%c`miwV1fDOR5(E%h4IKYFUHbZ*0Q8Qt3uzQ3)>|J|WEMB2Klaalh`vr6W4M?_)od8rM*QeSZ3v zYpQ}eqLPFEpMUEXO4&pALv`q_Q zdt;BEVGq^E$z+*wA4%+~eh0zTl;Uka^)7cSXY^#xn-%KX}tUW}}C&HUQLVmEtH*|By}IFG!NyPF?HL=dYb&n znj41N*-a<@&@SF;&_I!IYtyW5{t5DMBSw>9856U9V}lL>F}EMc11kZuEpump135W0 zlc5ntb<1%&k7d%rkh8x z?u)HH{`gQIzy74!|Igol`ukh^kA2&N3GUj}#1q1JROrERYZ=74!D&t%m zTmJXDJjeCCgVA1pelum+^4dn+B<2bB4HM1t(^Nn!$f3T4CuL5^Te&0;WNcfKq4!Sg zf(Iyo!z_Hm;MMnUT%sOZwJ{0)m3_;yZONIZYJ(b#yn@QxKIr{jdTTL@zr*=0Bb$P?w7tOtEBP%C`G`hu&IXzkP=J_f~vUG zjOs4c>&RQ8RCnlAyt*L>EAnREa7iP1i~f=*LoLJF#Y$6GfAxyQ4pNfI)ik0UKPdMC z7=ZQX9}T|We$Adiupe>TqtaS>26^=@?tc^PrcltgLo3#d#Q>OWZt{OfiT7-JT{GLC zW^d3sjrzFS0`)+<(yMhxme0N9ufpX*4cBF(Yal&)6#`ooiWQKg10#{|G|K`03hliw z2;CbZ!M8ectejQbZvBY9vKtsOByk}Sk^LhryzZ^=MHhk@D0VUk})JG#flQq4|DE^MCydG>;R_(GIX?1_#wXnE+_YD)o0QsE=>>EdQsY zDp4o(N)*Cm2x%1Zz?N;RB3{f%5-4{};AppyH3@3jH&Pktl$Wr!DLwm?>H_J4BT!Me zhP~?73MK`AORiUsjrKy|DbOflIZIVDX`Fi0u})1w1rvw1>)e}B8|Jn3!s zUPq}x5i`zjQ5(dJH{eg%yjR|!`ZB&LxFX!Kxc}xmfo!#q(@H(tKOj?kF6 z<>(TjaflZsoiWlyO8TPUSM-}!N3QxA7_5SCV;{2vXUB-Du3juZ>W_*56> zp(b|tn<%)SQqEbwrGJ@ndzTRD{31krJ~H}iV%+5Xsg<7be&4iAt@g0^(p0yhSraOh}bLi;l*bw?ZoRR&a>Z zjcdBi8GmL;lN^8Kavq3eRs=fjQZ>zf>8Ux&alOd2n;*rB3pspJRU*sp-Ees1Z31Pj z%}jQilZz`@Du2U$mtmi@>yjce%?9`$Em8fygk#?c*9i=8ctS{Sc4X3YI==-Yv{PBf zT3E;IOnLUDU>vSyrOq*6H8yQ22TsFLvVeLmv$E2yHa&id<$u)=%3U6E+n#FZGwj4k1Cb0w zPg5VJAaq*S&twWh_Z7eWR$wVf_vKUsRND>%2A90d?H9va3B>-1+jdpXISlYQRHT2EZ2)$EFP<=>PyTAm|CsmZ48W|ks++kp+ z_PZ{<>xvXK{6!AHFaq-6>cGds%vIH|00g=_!zviG)0>mjpz8}o>|yj(kXrGLdZ_sJ z8)Ie#p0bow$yyOM=o~aA5?I3ovLT3s0SWDnZ-4GsF&m_4!n{tW)%Qi7sHVW<4rQsO zg`ywx3XApEXAn_%h_|Cd0!z9gp*0Fn=o+FJMGPYo83a@hIQhY%dQW9YT0Ky?Wl2xB zZ(dmv)GpOo{13 z(R5V%oBp{?3F|3&sJH!;fBby9OU%1i*H5uOpQZtl-F9b2b|PgrGR}$b3|6gkc=meE=;0nF|4jIi39OZP6V zPsSd3En&b)hvh5k-}3r)bxp#!^fdj{heLE}s%u4F<2S!goMFAXB&j~l{DG%E(xJ=j zVu7n#p@60k%e7ob8UPWAgK9r~kg%;+@jZlQXg*|aZGW_PN2uyo^<_( zeG20Vf{mg{5dj8}lzTb~^QlH;rs9N|kYgN~(gCXzbJyiC-@4*rbQv6vHuBVGUR4M; zy)KFH6(yD4LOO5~m`zO#%P?GsV1L~xY7oI1xR6tJP-V&^reG(AM<0BLmwaPdxK$_% zPu7v(5N^dV?GtahtuXhNQ^?!Y*D-d-$M+>y*A6qtHftwl%7&1a@VZ*ntI7mBRV(7! zv~SVGNlcY_^zjcO4T_KEAxnjmMNsC^2i@?bU!B_2q@_~&o<&nyMhdXrTYq>|j^J9< z96RAB=+C0JqcctoLG>vyRuqEpT=z#c*vAGv!Wa1`>cab35jVyyMl+|DsGNuh?24{) zda%i_L;1CjuB@y2Mhz~V_UqR&oLQG^+K6Xgg$&Q*vaA!HJHtYzLbiaVuVkXLaobWb zGKtBh{-P~KkWv`P*XDSsw|_`CEnJC<6tv#;mIsYM=qDzFrA>2BQSNg4vW0IJF-NUd zH6K9p#;_gV;9qlR>S+!XL#O+x7wVz{xTbv1u+(W@ZYd2mBV5IK04P)hxyUNwlABQK1hLNwa zcc$01nzW`K-8m(7jJbhiSmS0T!2G4_7z}Rh(U1n1eAiw%>wihrn%nAL-_tg@C^wg_ zNNaYpsYKF=-oNC0tV7m{k?jggtfuX2K z$Y*-@$(kB!4S;aj2G%(AP6EM_LfkdbV$0xvHb0fM=S46*(ccZoc8`c?MDmOSaIyiLE8co#vTNi zL~Y1ViA5Q@wCyfgZNyqwv)ziYA#FPHjTOOHh+Z;PK|N%e8WF~)z_cYU1J)g zVnX|XdLExueH!WvQdlD6ms>8~JhZr)$B=jIx_Sxw^_Ogw~||uW{k}92xwRf#izJjJ5-CD(G&cA$MEsJBz7VI3htA()XZyzD}gtW&J)5} zZGUZ+8}+3jOvi?h@5tBg(Mb0WuqM@4Tt3ESqZK25;!%Wm6_(-(xfj=1@8krjPa+PLlR+4mAqFQ67@ zaAwsf!yR~i&m~pzqMdH&*spk24jUc_b$@)9r&kBKw4GX=rMLPx=tZ3YPrRgDvk@^C@*pfWL|fnX5-Y2 zEz|E@XKKMpuT~(l+7%$Fja!y2xKdALuPdSDiqWyqwrWe*<<&MderaJ{KGfcAK^YlR zt-Awdzj1dBJ*+x9q$Pla1$_k}NE0j_Y_dWjekq+1M(-_58mvB%l`sqpIe(!NNBbP& z>Q+vO%kJ%~B!lR%ezChlKI41r#U|Hj+;2rfXSU$@YXh&L+j{zF6E?u>1r}L;r>|JJcz$;}4nc?%1@Qr!y*s4oTdCj! zGI4SWzr>$z;KmgNt=ht_$A183Rq>Q{c&KHDTa`<$bcQpmLVaa|+>LQeXj-#eJ zV|O=bigIXU>N)Ca&4;X$!du(2@ zr*6LNhI;Gd3KduH+^txau8&>0#opJiX-^YV>oXA)}aKk&`U#pL4IQgN0SAUQ-y_6(w@}W!#)|*(J`c1p|VZxRamn>a3_{Z-*{SU^>4Y;@S z1p&Ay0XLJO85Fm`E&*c;19|7;wt1un;z(Pf5wGy|cb~(#cV)fVeTo58D*(Pag)i{p#LEz%x;^N!~R+CV| zS}n*4>w++3h4m5t<7$;4&F__Pj&L<1sD!H((W4vQrQ~sSLThV|tV=?h;DwF?&jwO7 zZn8Kde>7>x@PwP(8O@x6^nf>k+e9>uk#EpADZa6|VZjk?QbObCgi#pAMlXzxd=rHU z7HESOCSeLTU|_8@Zh+13!~(`MiQnL7Yq<@iW1J%!Ac72!g*F5%Hb9osc%2ff0y`ZXd8+Fmh=I6M$aI1I!X8S01>}`hj>?<%cIv0IKh%C-s1-O@4m< zLQLM)ABOcTCU0*RH3Pq_c|z?_x5E-UuMGK1z3i_0X}!!$kzc*3&ztIL_W|-0{&UGm zCYwlFVhX1$tA`L_tXg$AZrhG!fBIWUNAEJJ@dK0E>T1f>mMfL(N)e}9ShGAaIk`R? z^7HGaeJ>_YyZ*fH-?2D-I(a#HHF@@qwXRNi7E_+Sv0lP-M4%v}WtKJ4VGjncq=P-5 zPL4%hoD(tmp?ll0J$&=>qU#0>SWEpatMiW94u_)H1h$}P7!;_|hbWm2e~r~rVaH;d zO9LkOB$R0b6x04@F?98!Z`$FnMj1T;f2$Fp>EvYq9~f<=$G$TvO3yrRj3jW_=b>Fy z^Y^m`nCuJ-K3rd1JOtLg#RGducqF5>WRC(ik^v-djFs#-KZ$CIu1(iUGa?S-4Ai07 zeM*JhXVySTr`*0J#462WIVKu zCv%?*Tii#P`yw>VzWxsReWLY>DJ|3z;86~1Z5(|`Yi%Tl6?*0q4+wbt?VunJ>%)Uce?Pd7NI%#Il77@% zq#srfyoMW6pH|TH!{qhf^S{6Hn>Vio!M2aZ&|lYI z)g2MouKp_(<+b1JPJW4QPpf6U`sFzP`O9(NRP#4)VLk1%J8#-cF?n?keKf<(cQ0Y0 z^>SLb=T$p!uO%C7e_X8_H21dqN86wm3^LxX-$w}eUzXB0Apbsx+gZ(@N3zEJ?A3E_ z!O~2AdfWZ*>iL^$vB8*MpWG~m`s!7C(Pd-*rM_&ILw_T_IX>^s>Tkv5C*~xc+c&rU zzU5&Si+O#;Yp=55{hCeWoe0^pD`W-iYz@NFQv_t7D-Qjoe^P-tG%%rVHGoCK`8fwa z?TqEkf(G7u-pQJ`N`Mp6K5(?VzT5tNyTxk!jj+}8r=@M)daVE_A=TOZdJ4acfO|_; z;3>lI;wKn&aN9p2?oQcTt~y6<8rO3^MGTI8v(*7n`@1cru+)uCHqB1iSf2ly)qKxB zwk#t*|5#nse;-@Ki+OdqVw>I)@$TOC0u{)+?tPl9tGr4s4AaULM}qz!SrD9oE{IAYoaD!j6*D=l_#; z-#BNcxZi#{`wy=v_j+}uxlZvAze`Ge|8HdT}!f+O0tzovXxx9 z`f?2qe@MRWr4`n|{55zF>4fq*Lq*&y9JnOu9ZAJa(;B7I7#YQVL7 zdDI-ofEQtF$ZtT8ND4i#GBXzEI_5LE#q}Bgz0GtaJuKU~rz3(}3cQsy7(8-u#(_Ms zdf*t3tmE^Fx@_jvIaV%I^UJQU+Ve59XHH4ge=2JRGHhE;;7!(FBC`Y4S#?>#A7cH? zqVKvf%}K+*c!xv`dodmAMpFKpFUau21d9bX-yv^IH>p?u~_on`1dDBiut=RD%f8l~WWh_J{mtQsBN0at$^QWU$Ts53(@O*>; zjv+qcT1DSV!{zSs_-9>P&p?FncVxd8O?5V}@3Rj_4u`YP-PX6^Y><48Hs+qcvzhN6 zH;lZQjsAEurw49kvlYPdkyzfmI*u2RYUF`|Px=x=Vk|5^+D%m zUu*B_qth`;4?G>?bK8x*o8r7ov3paTSD7o7&U|dUx|(veY;Kv$j7z$ zN<|(Oc~s<4kw--y6?s(TQISVQe;yTicr+ZY+7O9l+sT@C& zEAmRsoP3ezi@Z`KCtu{1(m0i>IF*7pm7_=UMP4ZKNjfl_=v%0TGwXG=md!aQXwk_D$em%_)q~4rW?DGN4kBP}5 z1_9r#F_A|ud&t^7W(CMPB^`3eH7ai;vwU8>v@1ZW+WNoEl4~t(f7Smn8`sR)tP!>$ z3A6C$RwdAt!!wdFw=)TQUtM)W2Q!an%`oknc2ujf(jW<3!$SV0p(}=EXqU3it_MEx z!x~bHuxLz7{51!nk~Jn$xx~3wRrO6ZXA6G>HNli<3z73V=H82FQ7xB@Xm)efH>29P zR|uZB)-52IHU|R=e;55Vlr*cFc2wGoO2XG|P$8lAWcR~5ubL_s6qjxH$Eam|FD;ku z3m{Ta8Xxupdf!wxO_f!JD84)E`ceH0@mZ>M8JEi+ZNlV(-jD01YA;z&$S;>yqt@~b z=xC!SN|FQH{dlgqK-A5eF4gZU9Aw$8He$lk~ zdyVm6QOcn>!vYje;oy+n0eV`)GU}lP$NQK-nEZkAT2;YF9rOX1&bxX2yH3$o*NEv_ z4u6MwOfE+zf4SQHx6opck-sp(*d}av%X#qvnuoG z0!eZ;A9pu$N!@spp?R>E2Gtu5ul7RQkVN9$IP1H%Zo6KN{H1d$&{%7HW}9?40NNv` zq#$;V)r-aqacNkKqrg}Wo~41baG{3Z3<;>WN%_>3N<;G@eBnh1T;7^Fq5Gf z7JtdE8@ciBuh7wRaEJQ>Cyi*~4o-mA@}#-e=qxp#RwRivj2HGuc>ny7#?ruxkaQovw`e0+(s9 z=PR4}0QiE!H`V#xjrD{TGsetqhrhm;Gy6B!mF3O9eEn%hxL`LE^PX`1kk(#dTYsZ-NjMUdf^^rKF(y)M<+96ZJ*6$w9oUy%)n+=3LVBk`$ z)}p6V+H%%25S|G@J#FPH6YH6x`G08Q6-UdA0O&HY!TA9Gj#rKqeA>v921yBj_aR;I zmPV8Z>=D`d12TjfgdT5)eQ^(K1|M4{AMljpYsdr0mPww$P(QgOahPDXyK*d{MAwn3 zNL=R%Mva*RjNhCl#TPXIJQjZZ;FLK88lR#NH$*8=4jgb`Tb%7W>fl?I2Y>jl5;!s0 zb79OGL`f$^0aeCVA+ejfx}8B))gPh~MnI7<9SoCoSJM?iRjstg1s9Dp1!nr5h%Gxt zX?Z{f%1ljGR=kn2`%uQ1wnAOO8K$3hMOJM$=M$+#JZu6)?DcCog-6Z<`Nol^`86mr z12!YzXqUErG5kNWL3CG{4SiiS%n!N#!t1PyUrMt|%Bp;#h3qFS_Z zjR#!KT@rNbx*9di5xOH5eAibn2Q{UHNIHarQR;4OSG6K)NO|*)Bo@VcR#hh0=@k|A zsNTZ)Q zGalT*>Ss-`cYA-vQGfI+xicp%e`o1-dN4=Ag{qG@UpQJ|hw$MyL&7`j0I{j?!#DH@zw23*SR?QjNOhnX}|gzC&7xqyie5N{mCjuvgV~2 zY3NZ{f#wpvp#oXQ2RI9fHlUf+;`&5&cYEVz8WjV7zgxy1A%FNS*d&N~pc9dp&gM7j z#40keF|z$4Sb$i4_KTYT5Il2Col{(=8bB4m;%*~uiPyb*fDUq>jh;;VR>c!lgvt2k zzzp6v^Kd2jC`uqODaTKH3&H&Yw#wQx1=_HlJ3WmxE6%{dSP|9REhLiA!;qZ9qJR)1 zQ=?GF>oD{%i+`B3xeMq-w+3QMj=o!b2}L((QSLY;vfS26=L+O zDJ=nTpfJ*oJ7pkFbgm3=HW$dfmva=>1gE!XBE^(y81Wv%J~?nhoaW}jYCmUMG(}%i zoCiJ z42EKu@PGH9UGK@z$GiRYO(ZQou>vv|vhe?@y!yl(`Aqdq)TfIql<(-1K9@)Q%{{4c&%EB^@^oM{DqiV3Al!03=~W zOCPqP$jHDQ;ng`Fx_lb>3V71;6=?)C)_=u0g@g`>L)Qs?nT6THY0mK16Iq?`nkb`; z>l>Ne&M9=?=IS}&Q8-ixbNELpMFdNzY%wVk!{8a7U~EPuMqyO2GDv>7<26xvxWDzxsdDUyNJxBjmDi9cg$Zd3Zdpk4SUVp~b z@z`tWj>8UWxbZyJkh%<=zu5;OBoI2)PRHr1H1)x-kd?tz(6pkaHJi31vab~vMfH`J zKq(49gve2WPVo4-0=JfP4pnXmj;XRm0s(bp&0~@|u|`D?<~7-Fsk-wHX!*~t9Y25i zvAFZWUW#>!O6x`B;I-Ry9y#MmKYzbZ22`zQYLSiCNv#5#(LP7t07bDZ=xZFw=*v_v zTNOgjO16>e10!)VCyuvAF>~)^fcaIkG_lH8Rs|2daiT-c_jW8lDSIZIm~;GoUe~j# z*YPsc_3%5q__0qI`p+#z4YY*TlP9sCOR2@s6B*ys z0>1XVD%^Guf}$LWlo%bRJvA)li;;+F=E>Ctm>V5b9T9`xdem|-qeiNOwN-O5Y(;g9 zOfrU(s1Z5dM1d#GDjCCJR(}hGNd0zf0w8c6ZzUfsQ&@}jw4^5|Vc#r7yI^TJnMwP0 zh<1Y5KkvOt2eTLgkK7I@D@Bn&VN~y#iUWEz49b%Bz$-$JaikF^;6*EYOx)l$8%I8p zY%!0ORrlGN7{hsU=44K*1s_~_J7rNPm{@YXN?j4 z4M)jja@z^bL6#R1vJRbL>>LNfhPFJXxK?5dzv1dt;#+j8J?g z`dyePb-zA98uT{&*MA9k?qao(ouAuAMVy2I6lDYm(lafL8&Mz(8#>1_%$YURX!A6- zC~G$thM;y@*(uLOS}u!DgZ2$`53hz*%QAnqQ-D48hCQa%o4o5;P_l1HG|OXy^Gq@&YefC4_unLbMP zxjw>;xO)Z*xqtZL));=0j@>y@uohUOr`IqMpA7dklKoD~$qLtQynknE1j4XzhQ32p zA|0kqpziXoD5~5R6v-|+E-1In_iIs^6Z&&k(M+SR;u6Cpa&r4`5_ zFe_C(7b;<7)lDeZnd@v$nk(D>b2pxV#Ut|=pZi_QV1JF^BCm+knN?8M6t&rG!G+l& zHes$UkFD^jpj8M{o;aA9vB$29f?W_gz3oO_j)D6{SP>VsxoR);+@*jv0~nrQq!We% zF-)&2%?2~QVUM4shQc?CP7@<0G zQ|m+rhJS1kH5t-;i{$JXYA zk$;7{$_y74y~Z^j$gg>(r`x4G#qP4?QHP)am-WM$JNICSf6%p1i}nV}(X|-iQ_sph z5E65fy;S0kL2|p?qrdXX?pq4Wht7g?TQY%L5N}o{Ay=E|}wvx3PY%Y4D?RZq+r%>q8k!upa#mhp ze6>%MS|qurOg)$1n*QrMoLr@)X3f*H_KqaVNKw10j6$e$iDFJ8YFXpDN`HUC!#E<_13vXhGs?0`ssNHgQlQqKx#d&A@OEi?fTxe9~f^omBz0p6jYXXD!ORY zA=c~yX1jLcMUOR4x{OSGHvmt5c%xupGb2~)M1$dcH?NNxS>D+w^e$E2g;E@!2?!J6MwIZ%IgCyFoZU54M~>)e7uidD)!#Ti2K|f=jY`qUTbBG z%kI?|uU@SBP0<5{@+S zJ8HT3X-Q!fifW0IJ6BYgIwc{dcN8b%CmfL~l+Ur4>xXek zg}B0Wc)C|HvOXy|0OQ1#CHar?w0Kv9X+XHAiEd`(=1@H?i0fReM>f0e_=7-bv{3RG z6q^>(bsZQ9#8ES4%YP3Yv~42A#6^_6|4kg($Z2`Be)uCxRyY#^0NERQYKg3HHK=LA zuX-#f8Se;MGud#xW$$%dm{1+U=C~0D*71gndAo$9_rKrLVST|&YnL`P?yQUCB{brm z*~#f=m(FC&+UM$;lYsJ;mhQ$8X)r}*rt3s|GO^1cM|pg!Y=0R{GbW(95pwbcTu;5w zkEb4xwR$UZJ?}`(z|cU7vy1O;w7clyFKLRyKF7J)G%PC^stlG#Z1MZQ|Im3WFIVWe zS#QJ&(^vSkTw%f%gBC0P@WXk>YQbo6{p68arqsFJtxhX{1&f6WNv4#J5U0&%OghG# zJ;fYb{r)e7HGj`fro*PAo!>c*M!N9M?-_~ATsr-Bx`0`tIMmX|a5Gd->~c?|%NJJosDr`{|+zM$+ZK zZR&5AqJN=dUG~q*pWpoven<2C)zNIZ|L($j`$YZ6b}osN?2_{Rnrjh^^y! zBl~OqsOjQ`JyUZtrGwW>dF0ZJq4hcU`LsEcztQ}&#qa<1#DMui#xT9^d)Tj6k|jXD z`yyKqjuB*PLy-@cqRrDti$PsQEGVMzKT5@qP?wZs0X+gUFqa`w2o-;&J-Ln~yOI8U zMVl*QQoIkK(SU0Dl>m9GeV!moi&gZTaPOc@puLDeqz^e@Q9*LjcO!K1%3co5Mb;PJXxUGWO zHzXA-?Xn{Ky*J7n)+}g6{gLcDY>rd7%C5s4w(rsDqQA4x+9NL%l0QtWfXxRzgZ-_| zW2XuG#33sH8#{kJB={>U-eJh$5kVTEuVni{E7_XRN;dFfCAsazN)~>Al?-~fk}kwU zC9`a>hN%Go0Yvk-+!L3>VRM=xA-+zv-ZNe4aFjl{f9gXp=h>VJx%oyz&-%76AN8zn zb>Emq>>il3zkdoAtP2Yqiy-B0_9uoYp@Sk>(cUBXH*|j$5S4e>-kftif+H3^L13WA zO14Nt?sKH49d;|YhMVd*XNlQ^$<}<<=18=*^H6RHf5ORiG6XYpdWIE3&?}mj+FttsV#B2i=^$X zh@%@cP$z$FWbtH6GVr=SX_`e%5`|DDiPYLR;I2=p3qIU~j%;r^BDO-hMLk7!e~;F8 zc?{Bi$NM4MLq(D}2DmvjVOR&mJ!|MWbyN01-wFj}`z5{VVmtWYCsc|YZX%?C>|*pL zy&A0!6ZHhJ(PG3oxh_s%PWFid$vM~ctbZuQ+gpF9Bqh3aiyHLa%L&2M*2Ik)3?tEV zemkDlPgoJ1VfQB3oj_tO5N~X)6k))Z&g z=3~}%KwVkZqe;Ii4?7zeZh^f?eH;HXI|s;DscXO^Fd1RNTCdWw!Xc(H_MH_2x-sqZ zK~^8a>)4`Pl62tAgfqc*-CPD3xQny_3g3SaEzH|7ER7w^ka@#>aX}S%f+Q&$L}!H0 zGhtp$_9i2t<*D{AtTD$*O$FzzqBMYo8bY#@BHv2vmhTygeYrY(O~ zEWR6QqKX*%$s1LxsJ=C$yXAeRrf`?P0QeE$^egu%T^S z{HE6ajtvcc$#^({bk~NyB(kFKjZJ^^oc&W6t^;x;h^`3E8guBRXQ)3zaG{8mn7bzl z3z&p{YD?2FYL+T3O~?Mvb-Ind|E;YvrfgYE^C(|7Cw$&SG^Of94OY1oT9bc*_tI>1 z2r;PcR7auyUEN&2n2HSo#mN#&8IExbW@CfxghC%p5DcuO*Cx)6TvR@6a#Gch>eehg z*h`}@FD?j$mKTesy`gD97}<_t+qOi|&M>-b*qIj3+KF_@z@S~v>|XEU-h-@Kz?~Wr zjOF4bS&DEO*{)fjkwdI2QoMgkNCI+eNgXfo^Q#!PPxf%p&Kg;mufd&gU`;Cclou0T zM!wac1O>Io_%kWH$K))YnE>ukenDMVRtVBFYNY%Ss;IpsX6=M7D1w?0FU4)7j^E(7 zg{+W`q&bBPN1~#4y+ckLyaZ)#IMqjec%4M}=01XGv|^COBsWBT=d^zTws2#6nv8qL ztPiZRNxrWhLng~I!HnU}yp>LjZwZO_$hgl0o%u4^m&CMQ%y_eC(e$jVYO!gxP_t5cM2 z5qh9m&a4cxJx?Ld{m9H}{ZMR6B#>7kMJ`d;U~Ijw@N9dlumpcQHhS#IV_%xVNCLK4 z!=82UgE^*xY9=sYkizTa(bOuc)2zUCKDqc)+Ro@zPsaTMf6Z?p0~Pa#Y%tSmf>GQ{ z2iTPrJ3!1w#_xmG&1hVsF@mj`z|mk&Q^0*RqA^H?&-Z7JJ4}5I8X#~A06NOJ^qB=czb52qm12WlvA>jnA z=S4R;zK=48SqCdh5T~mUw~R4xYh3>RWaB=-8|mkgRg&XZWEBoUbh6uFt&dpjZ_3nM z&xbrZtKUa!$Xat#nM2F-Ko7h&3*paPWM^*x zNwV>(T{8S~-aHYC8-23U!w54YZ@OUUE5cPLpO}QOP`d+Z3BB7!m-7)*T(~i$o3dGo;dCcN?Ab>EYFQ<+7 zBGG?YGNFIUg2y;7e4RQfky;x>3*OXSjTT{MU$!(oi&*fZXwqtxzEp<|7abO2u;i-m zC?~}uSrPy;`;<1>r@^I)PUIiq7h1oVSivG3czexvU1~*XM{>Vem^T3)hZu(KLAk+I zLWtxhMK_tv@MKp$7&qmE&>GhR=ZLv`%u|t?Xsv(I_TW$)t(SDy0JFrT$vlhm_3uMv z*I+hVp3`olqd!uNGR8=#B>ldaj;mwZc4iqRnd` z5dC7aogtcas6nM-L2{f^-V6%`6g)v#d&x~Bl72Q{E&|+cVz5Ux#I3V@2Z2$BvtcS- zl&OEPwnSD&nj}JG#My8XZil|F6dSafr`oj0=VqC=7!T6M#(T8iVad!T_Z$NX+$GxDSg?=kl`0#!i9@y=<*G1L`>3ksvY-*#s?UCHhIiyI^ zV4G9idgx>@Zk^m{MV2Qr@=f0AlcmO5w@ZJ6@6tEPz1Vy1`)cn2x51tm!*r+R-k8vl z9@gaBK?w0NMzOgrV~A?co9NV`G#7y$xma;=t2!^0|4}@$_63$hW%#L-Lr+T4VmL?CC3}dAj*Xl&!cuapw zN0?H~X19wb9m*3cN)f}kn9J}0r&gx$K%(%#DG6zHXhTtsfQ58%6hWw%Hl7lTp_oO6 z#{>+BHJ&!Y=1^l*tqGGyS)TZAJ0TxPMb-l7A-)ScFa+T^R$1F&4z*An%cKUAnnoRt zf&d1{x1(7tDqAjsya0hx17UIh%V&Rla6V?NMUwrS;tyfA>xL`}JM@E`-E6qc>Ck}_ zBxu08EX41wD9w2Fb!(%*O;eZ*;0#d<_bN;VE!xJrA;|XN3Lb|w@t-)xqMBP@Jnn(m z&StqCu+LN@G!hDnG&#?~JfL}U&Q(U95&CUo#tns$+anakBW$rt;deQi^V5Ig7?KXR z3t|;XkngUUD;CQcQBG+u>SE;1kSK1k^6N0>$7*qCKZjIxcpn`>7D@Fj~qItx3|$9#;31YY{3orQ~xeYHbpi^&2M+~ z3N0>ADM1q|C7|J@?nY6u_tk%a%)C>xLDL{ptQiYJq;3du(u{+DA=seBR|Ol4GW)IU z9-bNAHkiXII~S(14nGT#kpdD9o@9f9X6hv+?-Epj*T@^&3qPjVIp-^^%i180o*-rspXEP^U)7^ownWLJyi;*WlP#;1kzwOa%t3Wi4-AX z9XqqTN{rROo*gj*>{@VRnZjHA6njubM~j3g`nrk@^0LVfzlx%KddgSw(-H+UdU2On z6b?-prEvN)f}yO1KAHm%OoAXUEPY#+6yN+*Pp=PXAgw6F_5y_TE`;7*>AX(}ZVh&+ zE#*=m{dHRV?Eb7g&S^MM4_6RvGI%lRNV%3w%fCeX$q$PIKB8I2CE%l0Q}Nm2cD?D$ zzgj#s{c)UDQ*YQVFM@G5y`kI~sK{=Dn+JO{3^LOapXDyo#VOUI1t z+!pD`?*7x!a^WekFc*228C_EGf^z&L>D#{zB`=2Owq=NBAUF2vDpPx1{wAIO%*foT zD+kl?i#I@fbhSv5RFWpCiI2h67%CH4d;FD8#L@afbkW0cW$LmE?}9=)_NY3ZeNWVg zi*@^k*|XyVeJvwdV|Oy0s57|9Z%kixq3J{fyUK!kT_gOhxRH1^f{Tn4SD9=O=818-+^)dbK)G@a;6{a*iVcIW$?K3ZcUbK{4U z<*y;BT-2ke{#rZ6k!A`r#$2be;COk-%tDng&s!nDvlFam1mzXt3Q%Wl&(=h;Matv23u zK}P^l(i!}Dv^bwPAuKqy>f-OV6Z8>i9~st@>J$;=uxin6WkcQg^2gL?1MCTB{*FzN zBES8tOg5MPRMBi89ptjK#RY%;&}1wy*;T75?ype3V0S0_O*D7xV&F96z;!brk*Vp_ zdW%65p;q==y7uEd?~D3-qN6FnNsY~(6HhK+DEuOVHzxvN#s#KanP-Klyxc^7(qpD| zOm?i)RZn15YDKk8(EjMfzymvo!8o|K&J}bt7^??ucORS2$?{!2OO?+{mCsRTq}sbH zCK}NuY6ctPi(f(kD~w7&vbOqJ49voawh>~Wh+^C$26@BeuL+4S^!hBX4qPGY3!**1 z)q>$p_5MR=NJb879n*ULR5EtVt-=Jss%S+666tj4c|t{Vz((r>A(B^LxIKFpLc%nH z_@^$k&i!X05|JMc-DsEyG@9NGN-i5`O9d9{A{g=>*HnU$JfXk=F(ct#%chF8t8#MV zIOgqCdNLHIgg&?@F1&&di5_h7O@skJjJxqW6jnmoh_8!=2Gs#u1*@cE&bxZmU8N7) z;UMrw(W+zXpSUbLj2K=Dwp<6-I|eY=xapTrHL|WYF{v_FQzhRzvxg|&zs7$P_4;&X zcbDRuMw4shHh!nSsAGBt?MsHSm5NfPLK(IEE(Tn$9o%F(-!UOU+K@Xq+chWML?| z6G^JtiMQ;TFlaTOnR6!S2g>IRn#SX>NZLu~?J`ujK~FdbiS%sX7ywf-%%h1onyOq5e|6tthDM& z^q$+Y)xHWVbVX#7Hz5RYb;1AY3C1UDFHAnzY0IJTO#L~iyi$n1d|W>jaiRGX+pnBd zxu)_jM4Y&)TD@S*5ESB*lrE7^4oT1wOH?Eq6zmv^Bsrrx zsn$Mng1t6j*ElClD{UDWOSUxrS|uS(Q#|RCIjJMX!DojZRJ)E|96=EIE_}Z!?<#O^ zBe3tWO!x9ev5&u=!dn}c91rMljSX!>-edM;S)uGadhNK`->k|9x>W>JnC9wmk44fu z2^MddbRFXEBT&!YL1XERev~NGUOsw?Ez{EpltB2uJZuQ0d7%TE4TZ- zlRJ6as+})SU)l>hQSBA6ppCv?qZ@$Vn?f5K@AD6Xm;g=o?l!ir?X3$q)rCveOuGQT zP4<;&E#VJGUn*O`E&Van(ii2Bu1>D1lOtB+5YFfy>-B zlv4~6{+%8VWYFnmU#~6kzQyLnFa?Bg=hq%8mFgDHF1kKF{I7bMVjkzW=d8XH+ z{IdYoB?mM?&ED5IXVJ)HiTl1Op%Huq!3{H_3FSOrkP_M^cl=_$J>RFLJO-h@lY#sU zMIjFj--pO{_B9JxfNiCs%l<{2p6$pHXe~Y9r3lFZ1mxpE&9ntPxfoW$^&JXMi2WQj z?2h)dgJRJyNyoWh7u(B5+qQb&^4jCm{|youhZ`5z<_r5cviB3z%0CxXNW!03NF4Hz zq-pn=Ayu0xj5!kd4wtHs#S{DxljfQ{!tz-wUI%=^A>C*Gu93JEn-~%bakTgbGhRn| zmw#IdAh+}Ui7_5uf@wE<=4{=muBlZOSdG~noT}?4^L10k1#>V&jNoRit!AFt~h9XA> zz_P0APBFvr-o0xm&Of6x4zW6JT`Pn&i{A|a`!M+tIHog+lo$QZl5mXyK=&~ZS;#&@ zF4Bc``rb>JX1b=#2=%|;O-96q@P_ysMP#H9)1aa(haQwh1H#tkbib9BEoyTI_d8~T zug#_><43<0#`8~)&>9&B3xVlR<~I;5@@@k925p(`w6q)5yB=*dyc%k?!2@%E$K9l{eEEDd@lR74?%Q6(jHpysFk@lohMQrU z_9e$%Ejh6aYRhiKC{Fv2)U@krk7@;%KPpmeh&)K8htO1-R@3Z`VRkAaOFz86PG9W1 z3DwmA15}-W@yIvdd=aW(b>HR1`8uwO$Z-qv({v1{}PR(bu)_mi~U}-r_sL;u7YO-s@ zeLT>|Dd-tO5D|YzTK0bCwEbf;G2SDfejD%Y+%gT5X|0xu(Mj z+oQFW;-Xx*Z~Sxz1QkNCn2zZp*f?sVviv^YQ?g+Xd<^^9!Ve+e8v89)dEmGTlWXh^ zUsv!!Nbqm4>zH@^v1Dv`Z~}}~$#nfE{*pqg-j98!=0!1;F!G|GIDx`bk*e%EplC)U z`z!OLoSXlon%#(!CG_WA6F;*v?Zu2{ z|17LzzxvqdS;rU-o(|PLi-5ZNeu1%R#Fi;t^lRK?QbZe4DEmeNkN`bO(B0!QiF%bd z%wP`+aDT@W$x2YE>>``T6{mr9q^B4;?eBK+wXP~F?G4|%BwQU=TG)2~D8DFDD?CfAXQ$rq0;1d?sygXpXf749##tfo^nbI6T>H}k< z?lH;63Ph;NB$JZ^mI|w-96cMjonXZm+FVoY`P83mi!-NNt_UZBf=u?-|A45vDp%RG zHI-x1J$g^54VrXnKIm;+gcV}S9Fa#Q2t`FeB9k#Ocq|)!q%MHhM3?50w^z1XBrJ=M z?A8W=@@YRhdPa%7!Nf}~RM70DliJPYc^BfNVKW=BQD^^eAD|cKlyTJ3K z-WOaH85;r-JuhvT-yT{4izLg$2u~-7P`d=7=+->_i`%n4E)e_~x2o>-G=W+jJIlO9 zea)PJZ@*L)`vfr+jdE|}>4-E0)A%$f+-Q4O5u|<v1(goRb!M6ih@4NkC0G=;Ua9HfrJ>( z7INEwk5=1qNeuty@Hgwl{(H6>$)}ibcm$&F?{?{&Hn;4cV#ib?zI`A#O1a5^mNz2% zS}DxDtv>^K%yHw6v`K7f`Cv7m`M3plq>v;!Ef?<$jq+y`BxWqhX=D6lR`oU8)%jVE zW6ZZ2W!hY(Q|N>ay61aUyUJ8I{>P;jtz%`!`NH;8-@-j;`1bq)M~Hfr9cBiHtQK1m zC7l_I-0?Z5JzvJbMhGCythJUX|GISjXT*D(w7NU1HCD-O*>rjLBzwUm{M+SlH1Hw& ziyV`jaXB}ANbSS*r}CD@0os6(LGMnGveM_bh(j`LD8;{iZNL0+7WEoyQ#bF*mp$|h zR-vpZ?&c|x_=L+X^B+@}ve6iU)0Ix?mGUh#LgmiDV~h zlY-j>UHy$CW~jXXNL=xe`J_|s*JuN^|9snJ$&q8YJKGm)exYF$( zwIs%=<+kDwiW1P0e5p>NjCTB?8#t0IiiZB1gu5UxFlKYI7xyQ<*E5+F|Gm>U6OaKt zuwyXZ-x#7pmwGo?l#!1;(OWzjo6H`sXmTmmoi!U~cl!QcPE?@+?QK0tw|i$5Nr_9t z`t88F$PwA?PgKMp^&mFHG>G3K{2RvAY;p|LANSQJT9@4}> z^Y+Mr@%D(QckJ=*)|dl$0;U;H&yf9>^BFyTjL z;WpUXeP*MJX^N)cy3nY1>8Oz@6@6ALCA%YJ;8@mAIlOZ>T;`JINLB7ebT1~j2;XF{kP zPghD95P4`D!kv1m+9La`pvtNO+C$v zM&3j&DwXC4#;k(Kws_9rAO_!aI?B|`?5Uei<7!7wb%^%zi9pzZ9&0gV3^SXZ{oV3BD8o8Doo|~n^=PmC<|*r=3ntL#4i5-NQiBoze@2Z2gfbXj08y!De_<(+C^gv>^d$llD zZ#o)dbXvas@aG2wm=2ZK6FHbX^eNOt~ z^DDhY3oc?!-R@0uqc~{m2L|t}g9-Z7DoOgD$AB9SDw5((UA1oOw^Kv36^>(i2Le0s z*l;Oh(rbE`-xk!~L;!>iX#%WpWvN%5iyiHil z^~8d%@Hg$ujI*uznD=f90V=|6_ik0;*zGKff}y3v;)jPMQ5pQ4#*H;7!y--4{Z26oK#4H$M9EX3* z^~x@+7Xk44a)2S!@_obxu01z2-Urju$``j9>4azkeh@@iker==zL>6!h;c(jLJGyhY0RRefCCC|^cJN)QBJFT3S08HIC(;n zRmTc64*@rwfq&=}!$o&uiC@uNMx6ui7@vTxQ#%Y_>`64;DGKn zitnm}JXf=&4f~QP*rxerJ zGtp+Vhm0_ZEY3|%lx!N8F^Eb!8?2~I@Rw!;tUOnfeXEwfmo-^y6O584QiRcazD-d_ zQ9m5$n_!vmZV;jVUv4-Xe(jCV_~f(+Bj0`Y;Q!(-VJ}7{ z)p-Jym%`{mm1du7G2eYS6q*Q`*v#W*r7Dp;V!vnhxt(glq$38k&CCDd4wn7qE;PFF zXFJ#{URe%kx5+5&f}Yq(vy$TkJCjhwKo@hlU7Zb-NV{oD#-COiB_&2D{ze&Qnsz#q zv)ehvyx-aRsYjF?&-y~X@uwnKt8?!ATZ$3T*>ISk4h6-^2?+wH9)AM9VnJI2eHj2K zHkf&6TzHjt;}F=gzks$_f!l+uDCxS-&SQUVBjIH04tzU{7-g9+fw}z$HJtmBv^-&j zaA=jm&%w8~Dg~9EiL_!*pE!+}k;yd+H=I`rCLD(p|szpIadlY0_LE zs!yC`oD)OIy{OMMhi&y%w|mc@x}ld@7xG;3d>nKzNoY8__;7dg#)g&o1bx;)qH9_( zbE#Utdd@o2E`lEBZlqY7=yp~~cg35ouxu>PyKr9&%Ppc)qs(ng%ki))&b$3(YTC4h zs3?sG{245f(SvB6@U2b7LHWFx&S({wS?SgFOcEl$;3FY!ETF()vhV8q_ywotre2lX zo3~khJkVH=b+oI^RCUb%VtxKvu70*B3frNg3c;;w`IWI7?sVgLtS04fI*dc2HVek| zRD0)EMnVww$Kc}}ZG<|*lO5Z|a0cD!{IDRlSHi$o>9=tSmH;p_5wd zu8yslFgfHtshEe-B)=Ukr|g_*<{D^02;cNnUmc;~WgSjZOC#?OY8Ay@@(x(>NK(-EfBsBv#b(%yQFtAvHM=-4KYEP$;(i$!^Qzb{00X?Z30c89V@{4BSgM*P({P7coc+QbcjGTDM`1|dU( z4?Po8zX75?S{JD_e=Z$Xvv^Vbt`P3C3 z0J$(UszclVtZmgdoyVT*l)YZAE$-3M=|aTXp9^qVb8jw~zQ#|#5cwo$hGi+0HKy^GqH*66o+IfRsl%C+hM z{$1UqD;*J((fE#`f59znkO(b9JXK#DDGdRveVFoPaw?%3{=o@AdDV3Poir#ig*&_h zkAa>{gLCXTQ$Yh4#617GFhd%*jU+il$Im+5r2ND;F|rJkdPb@XQ^_&bs13!y$C)tGQRrLx%Vv}vqmLei z8VFzKmYQKVMlBP-^%HqOsc%^oH!HheTY5c)WuMIXptwWlMqMJ;wCWXBL(R(6T!y^T zSW?6OaSJ)WNm@8uCQ}}YryL3=(IxjLQTIZhEPpnkLJi%2m{MURCjAhn<&n}k0;*MG zK+gHfXD6W(NA%%xGvFX5B!V?3En*wRl=T8U0_ewZAXN0K>=$c=B}p>$AJ@!{CW zQG{lcwlAq}^wIJN7}z(g$%^dOFj++ZMtssTb2mR~!=Sv!-Oxg_{INT{MUa{KVyHIJ zi6*Zs>C=l)$dV0!4JqG{V~8 zUXd0e?SLh4LL@huHgB^WtW?b*L0dLrrb7vL-gXk->(v|4iaL>JG0Zu_ZS*ZYt}$^& z(>DEQ+*lXgcixkjXxmV8Dqh@En+uh1wYNlUKfLyivh_kTQlQ$}TM?>LbTD#PfX;zIkwc7{-()8GS@>S4VEL{&Ca7e!- zR=90nhrV|bu0 zKGg`&>15~*Iw#M*?B;wMeZjAl7?hGOI7yCR3j2<>&q~B+bvqb?GKop@O_j%ScD%cM zpZPZom5=lfrpd|GXx1t<50h1|h%Ia$D6AMfr-~&l?~(MzPj<``J`TBVN04PZ4t$zi z7r_T^@()msxWye$a$m*Eql>_upT8c(@)=KovKtseRv9ikP9X`hY^P|@qHBE+1v#TI zEhYFf`f`=1995Z|H^~u+X>^6PVV9{*(EjkYyw?PYg`O3lXKcB!m zWJZ2ffr<&`6U&&=9C6kEjTOyCB-T~sL9wXrRoYaSK-f-3z?x10`_g{uM(qo0bW|M& zVni)xNMo|z1a-nw>gG0-L+wTCatX0Rb%oD~OdP$-8Ct&!c;ZIa$NL?<2zF>GL-!R1 zpC&CcE0IJVZr-%g@OtB>NRB4GTa6Z>HUoo%kk>bMHMY+5VXYTgu8);WU5{P$Ech%c z4Y3S8S>DD=@qDcCHanB@br>ACuldt}VqJ~2No#1Q&3W7KvQu=8$VXgbjY)gW0i=$_ z07s*ndyH-HwUC}iK+}F9F;(-o5_YHRd@D{!EPGF9H&9sm&U#hG7ryqEA1-_6^YERV z2uC$vWkeJreAV%SkzEdfr_(7e!$ct6b>)J?*swv|Kd34^SCQI zZuGp`?sliXBBlgpv2;Vu;};iOM}qf8KP@9S$PQDWbm z!3}71uyo39h#cbL{n4p04v+iht%jdIEon(S%S@;7;|`8|Ow<4_AK>SdPMH%!Z?nxW zTa+U?)q{U5WR`k9)lgzIS=+~KG+QnNbISO}!KP2{rcYfR*b0E2mV}DAWJK;;ROIFN z?bOwgE9k3T4<6S_H)q#|v+oy`l0P^Te4}g#2#q|EU(<6Li$H^YBrrTHwHElP@C`a? z&1+L*;6RaTp62|bYkvZ^gvc6g2=@%e0Zfbg`kzm;ENJ!X)Hp4)6KW9j(4ZcLZbXYv(SqL8pEP)qa3FoDcbN1ojWT<|>uy?d=BL zQ!4D%Izpb&{k109Pxh+DMd^%;4eQ6_AIJ_`$TX}De?>c*t<{8=8+S@uoh)X~&0P5E z_2OU2?5{Z5aa@wg1O};=^<8yShtlvjsAG$3mO=m0$6nas9{0=@7D76B&V@1<&$}lT zVOM5R;@AV$n!!Ck;%?Ndv{)5$6|)Nbh8ncVZKoWs;16W@VhS=d{3;=h4r*k(C~eRe zLL`kJwI2d8b2o{ws6pm$sF`0PWA};Z5!8Tv-htAL&l3m6=kwnCWAK!r78&(pHXcQi zeE*xsp%P`0>LIf$^EfEenTQtD;mSMQ07~S7Wzjq{M#A!*h6GxF} z6GwmFp~bIC1?_jmNB1-2S&6H4uL+ipzO~_9&OB_2SxCxwPXftBixO zH0%H*uw)*pblzjJ{tmpeX6uW018<(&`vMi$8Lsu*EXKQjKD}kHvRIYsGB^PPk23zl zr3Js(?=dw$o)zWXw>c6^(K#|f91Ol3_Zp;)e%qo|UKPv#M4d^0k+E;ZpqF>ASBj(i zspq&^+rEX`d8>rYvvP!pb)fHRNqZ5R#xx7CssG9{*u!X^9TETL67N&xz~Dz}6YEP_ zC6V`sO}wb6o)%H3hd4SL3arB7dkU{?N{@f(SR2xJpA?b=8$5O@c9vJ8oSg|>XDO(cvOy2mq=}+4UA~)`s*C1C%KbvNBRMA>K2=-X(n)s_Di<#K8MQD=2nmXMpZh*EZJX! zs>!MTT+!#7#vUw5b^yH~6C%&2v%ml%nHHt^w zaIbf-FI#r(Dta@ce^}!nI83^MPi6wcQGPvU=UKi~>1We=|NUMEoH`0S55ML4-pDWf zns4XkW1et=atvuK0eBvpsrS6YrVbf)>P{7Aqj)?%s z>izyM?JJjy%Yy8i{^vs)Bk=Cx{poPJb7f%NcKJE~yd|55N)1${n{RYBlm6e~r4jOwA-)Z211 z=}A36zRutOb+9TK@^`NX&BMWkSZ8`}Te|-nAo)eicXQj^6aIdT;QP8Yh!=AI-(7j^ z`T$toG3Iq(_sQq2g17zPMxOtxUm@%KiReAIraV;uhSIsH1@a3*VnxNgzjM9{S^CK_ zXqHsLEbp1@nZN`6YDGQ#fplwZ2JCZs>(-59)XQ@<4mKkDdi(LdZG z)Uzqe%XT-!$GT~{HyX#olK|jV`1N_`uz}qVTXB%|L;VjMI>P)=o@w?FW6FNwzZ0_E zD)}=(b$iD(A#reLZ(}3+A->`j8yH4W!aq8nGA3ia=xCXAp3N2_Ic}xAyM=l+IL5c; zK}?yc#rF%P*S!KIoK+$l6)xo{TSOY5f$dpnA!l7CV_;{ z`C}qv-2hhRb4HEdrMsVAf!O!1aSFHtx(%r ztfLJ_fKd?%Tpd_g+g(zohB-GR_kJ?fHi z_SuYuPhEX7$t^Dit*0dS7a*|hvwZc5M?3kea5v3YeRVtDDp?JJ-M?UCbIcr#qF72& zPW_Ul?uj3aV>HKHioSZ09Q%QO!)Op&$n*pxiAI^I)}G{u4op_}%I{)#<%RBTeH!jl z{OT8$sWyP1Xf~Vj+ zw6s3ulT!N8szuqI5AtemGtMBPcVx-2>|AP+(!}7yKtE)xJ9a-d--ZIq5UqwArX~Kb zHa3dBmR^Y;nyHDjXa1?(px9h%=-G62u-1ZCFvU2%bz=7)da8rbe+z2Q7PnefN&gk~ zV!hn;0qxdtqzw9_b0%Z?i0S0E*s8hWj$XmSp8@*-eWDGVy{kz>5wgod5fa!AW8nyV zw!&9S(_$8JXQMy340UM4#f089g?QJtxDPu^@=b0LY55!*<6^M@&zt-LyNVlO*iR__ zdw94zTPPps4KS91w4m5BaCy|$pwO*N$6%J2toCo%LbQ;j5=(r>_;uRl&Z}(b-5Q*C@Ub zr2MILo2MWcgP)^fmfwI`p}*m$R`{@Kc$fyxOH%_b_Q}ThZr|p5OmO?JG+Sz(xB%LIA-7>~ z*N2^qfXjNMrWJ~7^xb>nQAKp_nV8Vl$!h* zfW!f^d=wkAzhV1QowERf7V@eO@v|`7!UKtLZpAx_6@^}m=KEAo>zNz#(NIE;q#t4= z(m2i!PAIV|CnV-6R}ll7!8XSJ@3V%ezwf8cOL`U0*3+Bd`rgNmNz)x13So^2gUwOJuHJ)e;0#i z8W3EBH^24+6W;bX7hietfGTXIK1Q;p9cd%z{mCpmoUk+d_1SFh&_c?B8R8xtv6{$9 zFh{r7wT)zX-y?-Q65H|gURB4K|F@Bwik%xJdm~|@$+A^k4w;2>J0C~W+>m?b0Z3|? z25~2V9!T%drLJDo?t0SmgrExny*NiXE@`9P=`Ndxg2zo4{s9gz8^~{|A3jO`Y*#mW z=2?luEe@iM(ABFfmcgrKXYTa!L@4f_{VdMr;oTc;iS~QUU*Rs0LxOH`lia2;0c%~h zqasJKgT`f0g)2{E3IyqDKMBVO1qdl?LYB}lU)_~9M|zt(6ml!J#3%AVg!T~)!r;WV z;pi8&_4+pz`vQc>Ey>RP3Y*S-m91=S2)Vx zx;1Z+(B3_7&UJ z3sL_N)Y7pn_soer?~h&grDnU~T?s;w5!Z^`{LvJy$2pSGfOM97S!C&V9$mu4<3#bX zu}wsBBE9hzcJDVf4UWh>O_$h?|1L1|4JAk#=8_k zKla{_e3>HBr>7J`1vs+X651&at~gKps>_cR1n#eoL}9qh`0H)3(%)f1m&^g2MOBb880e{{B7X zR-Bga_bEAxXr+bRYx)=e42)@Rzcu)mw{(orRtvb2!q(u>0YLw}3qdjQI zVQ!^Q3{=n}#|7Lf*6f>1-5%>2K}ji!-A9K-#KVW6Mw#g8KvzcLOfpkyA?o$4n*5Ir z7LtnCV;vL*C0|{CuB?P4>v)KI=P3@)Hc4iBt5-RqRLo1AF7~w`f*qh7!>?`LQYvPx z*4r7gzPgws0q@?G9UQP=)~OayvE$lQy5@F;ros3NJiz4dGJ4OC$HY}C8|k#*fy5;2 zGxu9WF7o+Fhu2Yi*zB{+Q-D)1GKGPlS+O*wC8LG>zLs;+5>mlE%O?^O*MCT))!j5E zQ-iq=SGx_O5WBJJ-yDlIo@Q#9>f{n+JSkorzG|5o(8X-4rHu2jX-zXtcNI6RWCKdb zD!}mf8Bk>P5VY2@r5~a2D5Vx6F9>oN@Q-OXVHmUb5RaIKRj`gKvvuX3!6RrPBmRrS zK(MVCUj@~6i?xZ&5|ISg~>5xVF-ZD!i8@ppb!s-9ci=7xC* z|C(B=EZ;oE-Uz01xOy!K0)c*@Ym;6k1k=GV3bdf1 zd*_$e(O$mWyARKW!I!x@J^fy+o@_w(YOR}2lLOMbHukG^(2^mSr@a8Vi|Ex(FsaXG z7*XAD;BNQBS9@YSHws6wHSq}^qC*uiT6VRdd4u3kVH`}idR$R%#oMkxm*O0>kKx#O z0Z?`=8ZQ{!v52-M$0%Abw!0R)ZO575rEZUOaSc!Xb0|;Wq7_H%%y4s9Ra9SEd$%#p zn#Tf`4!6^0Rz%|vy+2V<;e!{bEt_E-R`%|&b|l^3RP}2{J6{omokvDfMazFejLlKk zdwj`pdY8QrM)8ik+sV&@!K7_@^ur4A5ong{B1CUYW!+~s(yT_!Q>{-yO7W`<%Ff}u zvtl~&a5;AS+tYZS@{!Otm%&VJj{DViv5|f^Y1b!*?XrTNAh~NtgK85o}cq9dg zVWg%6r42INu{%hIx014&o0-?%zWcw7L_^P6hz7zn{Oj%8{s@NG$aqca05N6T##x^b zj#cEujy!Of366Ie-$RvRPQJJi4n)Zkp*Wh_5WR02`#z*#z%2Q4q)m(%lz(TwSM(0M zV}39te9vLp{<-kFvtSiCak6TZi}f^R4gHJ3NV||X-%69|NnaQp9(vdwu#7y;{x+O$ z@RBjf@e}V{Ld(daYsQP446tQ+T?h!SBXh7|yIIIU?*d4WWfMN#nw+N_Qt`0xJ?Kq2 z<-}C6Mqb8mcd_4@T>V&di|QFJ7RtNFnIGHgqtY}h)Q#OHTuoGsJG9c}D{xPdjCuVq zpY_rUU%$ii(j}*Y_PMsTn9!K1du!Tq$(jBwxUSrygBc?Eh(PJq1I8*J4A3{&4ugwa zM;-+|#0WnWzp%@AVjrtrT=LTK5JZ)twl&ymG>(Kg=w_&cA!Al8o6^V+<)YULOSWAbZ+1BbI9q3wHJ?$-2iOe8q zN-0HLl*OTdU~ihdYa{35Fs0AStKQ?r(ODo_-Jh?7`Ql@|oe1~qC3^^aft#X2hsefM@n+W4nOOiS?Zz-u!Th>I@YRC8L^2F##mpi zMjc#Q!Q-ODFnc`>S6)QQT@hHSW~)|24AW;ADpkEjcJovwf!0aV!IF`o$U^o@w>tV! ze~)INs%Hp8+r|~sitQ~twrUw+{LAiVM{!W-RXqc8%C)!g1{abmKir?Cso*RNMm9mG z`Y;eiHhyM4zyVE%i@>r=o`ZL9qhP#wX%Gcv;P*PbPJZJ zDObh0c;op668AOLU1j(lP49%6C0G-j|T=XlE;dI>7LWk&Wlu2r-fcfT>hqG>7|OZ zsoeK9+0rrUkCbuFqywI5bQT%)roZfQMx2bFT-&(jCq+)CiulUA9|?C|gQ? zPM9ME8=aIu*WTuBfvfGpU|?`?t|?|~Js2mqvIbWt&VQ?blFkz2pKCnC5QDorTm^Cv zL=gFz7}Vr%Dn$8nbO;ChkLj;Vcso}_8Aav@pk1Aya)=EYnXw?;CL9JFRC#ohn!7R8 zUa~xXTq&rP`&vt0@WyH{?<|t`iM<+D(861*7!7&J29 z(K;e6e;`0#^FZw{m1@#hIp=psU?d@h^-haEOM0PNb)R(3-Gnm}9NvfvB)C*fqA*|4 z=2Ts)S#IcWOnsaJOL{b5;pj&z7GUjlG7P=*zTl1+q2%nLUo*KFl!vp-llHgF`xf@` zk3KZEAJWjaYm&RdOv_!(9wk2uINwacE8Aq|^l2+s7;r8uo&6QbUZ5vs;hlFX!Zda) z7#hc;D)QClI#S4bKfs}p)C*RL)Y$fjPe*CTsKSEz5C5K;{ z3lYd=VT_60H%HWrsg&}aS{&e0^_>@lP~5=t~7h18nVkydI2Ctexa}nu<_uA7UmP;#&2U*3Jw!dvj64 zRY59%*7oGG7#7T`!D6H64-BcliuF<;~{J%6=u(b2xx{ZDuP{==HTi-=-Nh zthRXPLwMDy0r8LwLE}Mj%#s|RJg;J=yYKpE6IA=`Wns=$FX;Eh&Woo4=07O3!-?@O zkt+nh9vPdL<+S@_95*nm!fM8UTs036Kx*a-QH=;+`2BTFvCFC+`UJ;^3iSB@GvW|d za2(vJzr?>%;v6h2Y^lcKU|4{xJsG!C*Hg`ma`dk`(`(yhxD%^rn<`)CjpppmXYR=C z-l~h<=PTZT8dIipQ;jD=2x)C;7Hou}J5pJ`_vJ*7msjMygQxfL&~DGvBWj!8fJH^a zkGsGDQS-#nS>imNu@e_`CmTe#2qxBbD7UO5qzkdP{ zYYIQ~gp4voFg;^(hndHEtX`q%o&( zD8iGKbS7QbW!$22EW(s*^Ou7u<)Jgd217BwEPNoFkx{xSRQ|cYPN;uDg!L5SrM;@P znwK@oO9L+ay65zh8GV1EC45y)@UYtl;^|GW`|WTae&yKk<7q$A=OZ?jb%^>$7JEl( zcfZ?`z;@}IDg$7X2Y$SrdmQK)EkYd{`2Kh!zIq?){lQ0|4WHGzu%Fz2`GD1-){_}D zDfVNrBv?US3`aaVY!QuvED8NJkm(1HIQ_*>vt}A+2`i!BTbPSf_3%1oL20 ze%;q5&t-nw6mpt^2#!2o_yyazsFcC(q;1uunDfbI9^eLKf{a>L;;kSrFMwR);EEfe zJDY)9i_ZBeMdVOlRq!OQi1Dr`>pXVs7S7@J~1K%I(aoyom~1w9gC#s8gzygdcy~AX_Qg zw>NjFZ`H_|SEx&Cd|#1Wdzr*}3cI&(ad4F7qv8i}qw{X<==dplMhfu`yo9NyO!wZk zzDsupcMjqVS01CL+<=^&$g9lE-*?n@&RHN3mxZrKwU~Mr-&ppcd15SJuFJNKCTPx~ zxd|8Iu-$gdiX871z^f=;*kI`l?N)a5>I{1{a-XC%%`jtwj!5Ag_vkfAu~J`oE6+9! zMK}V>t!R?vb(@x=Q(0GLc_cHe5;*h%@9#H4#ea9-*;mjq$)x>+iO2p(BLtgpNhqqL z!wvgG;bOWHGsO!ROXZR7I!DBljH`467D{_sXZe3g3~Zs(;nUf3w6XC!lB>o&nETNf z$RpnRo`v6+r0k^>4pP`ul4(=PAMHY(iCP2y5Hxp#!8ha*I8XZ`JuQCuJ(jQ=u3G0q za?k4I|H34B;rxb=i0ITGX2G>Wnh)s}!s8)uOVTjo<{YnOioKRan;$$BIzvCq)4&9` z`D7=q;fB&G;^r_gg3cQzvk*^Ulc`r5h{ipCV~eW8rDwX2B&QXGb@J^;?SwA92>d+& zFRZ1oPSS8~T(2Oo>Tg{5kSY?nQ+Tt>LuOtjafHv_PZ3;!1fqyMWda|u&-d3jc}wgw z2tkCC%E!-_Ip-ev3@3l1Pq#-)iA&&oOt%&fic}G6G6-`wq1h;LU$IaNbh!hPt>(ms zxsSmE-fnzNlrCe zu+o;`CBfNQqEzS_VUMw13AyotacZsbuVlmc@=v%{fjp+~b>b_3IEGa!FKl8DNywRn zBtKqYGy)x5M#cAF<$#@63uCFq0&=8HyZ6K8;2SZ)br;>YjEe>itJeIuoTy-63@;NA z`qef+`jDdIfd2E#?R4hLFVBs(b*?V!_D;);CrR_7GB8E6-owOpLU&KUTFhV( z-wdvGW+!AyzsF<92a7(0-fs4tGC4UH^*rNS zw-I$d9hcrN3)YDxxc|0?9mrPHP8W5ua&;0kO~u6|`8!bYt|r|>5evTd?ZMaFTP_u5 zwnX+s@ZazG9!lI)1FGyoK$#XpZviI|G}AzVm7NVJcAoq({qO#6x^v{w^R{9x2`w2u zPdsHg4YR}arl@B!uM9SM`JS9QF-}ct-IUzS|4K&!8y4peO>KwTr+0E`oyDKzGIrnR zr1xm=4{9`1vBzxLM}CH~_&@{=uNQh8I*^VY$Dx8qQl5)SPv0S?rD(_Lew>R^C^uNe??Tm)8gVO$$B-6zL*g9>#mW zJCN}r?bsr^kGzX`0NLTSh1$G%5p(^AF$w`U*0Xc+>l_+=fYihsdou` zkS@j%uT3L^J0V~ZqO-0~Pz;AZlx}dzawTrsB;~VCtXx*fzaO-VUxInN_g=SF&2yq~ zSo0!P(VQdo!;Xi)S_%+gl7w93|1)CBAHlmis&|Ui8}nwb2JHBdF7woZ8vj^;6TqT{|b_)2?VrKJXMkU{4g11`V4MoeaAFLFZ z!rh)AsA}f=Wvsnib^APDbq1Jm2&YMjAVYlK+Y18E{oii_f#KY3K~%3^!FNNShhxfU zpTyqXZ9)EbU_2B!%0{W3lR+Evq$F9QPUgA)6(uaQ(d?RF?pz$}$Dygz+Uh~-E)`(EH9y}zt zhq8SDdQ4u`zwe*3nRx*_6NvBl?9_zML`zKANK11V5XIIVFfB)~*Po8Yu|PzM(AyBM zYj0jT)-yt%%X-Egjk+EIPMD8Q87SO%-!nIzUu5%YXHw8Ad$i>4{HB(oH$DRvn;w_P zbEkx6PCa#-1zA3g3h&f?MSgEB)8ziU>Cvx(%$=@ctY#{WtiuM%m$A_I&c>NGWj=!5 z%`a3J5cD2-b9f>+QgGhf{%*=VR>#BAte#>r&q-K;6>c_%!Ok_@f6i61>C}MmfGCRo zySy=lp0#z-ifNdD^$xqV0G)Z}qq1G1)?&ZW)gTXorD;3lW)v-qT<_a!vH#r% zE_#w0qou=XX$De1gi~@G>`7Dth&3-mDdo3&z=vizZ!gpGaUm1klC}{${$AReY%bCA zm&Fy@w+RdhE0%I(MAkkY< z0OXbxAu`BeqUlbo|9WHy*nBGc{u3&!_j+%yBHq#qVuJ%kO zGQn~;DGUzXn3K5l4<=Eqm#=gB-FN!U_cO0s@fl0ns}#o$vXYqf#6^*~TnAmG#;UXH zqKS_ZD1|_M8KG8~5!r-`q?Lj2jJkd&ccnE8a;Q^YI>U13Dz4V53~qy5>A1-Pn!W~- z+HW}x!A~Utn$^N6+xF1aqETGC$f4uJFG-PKfTP#n?oE_gRp69;R|Jwv9>%~$L%@kg$EgqSfH zGxDe$)F@=@j?ZccrW6{EjN+N0__i)0-r+`h!=3fr1`(H{tPSv5wPgm}xRVG8z|ef9 zeDfP9VC_Sgg=KpyJa$id3ZuJ%G*YeP<_cTm2Nb{(4g2D~T&QLXOm*2{Q9w9--Ak?x2Y|bC+9x+#Ml+2p51tL(!dAi(w+QeJi7) zu|rivhN8&I;tYB%Yy&%;hyGlJ%Td)O3A5Y1^T?^ zudx*h=Ci1VeAN`9!me|&H%iJdk?zco{3iN;loKY-P!(HSJMO%IX2Qu$7Yu>s$t%A_ zj=5vQO=fM=a52R|Xt&-rQx_;h(!MzL=_>hy<%7*HZm~B-lh0(w`o*ZihOJRQ0&z<` zZc2~owx;S+sC|3>xIw`Lf2RDJV+1cgeZTFo+*8%{O3M_leU#=#En8b%Uo7Dkwj^=4opd zbk)Wp0{Qi@&5c$M{Kp zGh}`XusC`DiP2j6Htsa1Puo_RwP3`O6NGn`|}pwVown2Mu=XT<=JsF2}KT`MOOj5_aa4mtBeSTD4DX8n0&i7eFm2 z_!U057ep2V{P@L)9XrFZ=NKF73TpgS>&zt$G_9FlC&ycJKOYMn-V;0tkkdJyKIA4; z7+PDXii_9uj_CR>PGXC~cxnSx4`Cc?DCg(B22mQW({C*ScCpiP>_M5~UQU`^u`TJF zFr{LXY591P@5WPOZ13(N`bT=!H6bz=3%=byEsy(vt!7g;6*p(0OL>2P5+3|H9oxk_0e(F*_EN=dY&y`rt-|MEirHt;% z0fB}-(FOM?-<@p))8F{AQ0&5_an3WuD=WVEF{W?t_P*-ptS92U5s^x6?-hQZ9W z$JIhfmg#X-33rm0+K574XjC}~4u;6KdwwNn5U?EFdWs#pD33inV+DHQE_RaK*tM>W zC(kOv-Z=>QTbv8d|6;SW><5c^{Z^@5p#75$5cChtW=|rfcC|(_BjF$kX9>1kma{lj z@Yg%@jrI%bfa9t<_;DBTkFu+c57qwE^gfVGT6Z$9kXntT71U!q<*e_&qA-|z9>T_| z$?dHiVqb6U!UO|CD_>H&`R~hx1ihz!0%Gco_2x0WBlfNH_tu*SID*DSEp{tb!>O^Ij zIjf#_TNS0jc6hZmEw*Fb|Dgu_+lf{I%>D+V-;iWj>vntd!nI%1x@s6$Rw-xpmKQL- zLB{fR4vrJ#smuV+FN2(k>usH9$M)`LnLbXFS0~ zm6I+dl}C*gW?_2&;kb|AN?MOqOE^UdTF8Qolwp}MQ&#N9|4_JWBUM;1+k^OKnn03q>bW;-KA$&~wSObQu+Z11(8~_D26vKtxbS)t z#oJ`QwQ;G3ESS6vXT-hr%Y2wEpV49*?UG?MOwHlXkN3X@W*~pFAD_xy!haN{@pcG* z3BG5iLQ~=u^z|vL?Xb9zU6ObO)XQBwlfPpIxGKs-b@)D~ zEF(RlRT)6cCmM=VDdcbc(-b4G)dkxFI{XrT`Ux5$4Ytut&2HW7M!BBf+()^hEKg}! zi+ITjY!2dBw-Ja#3}#kMYvEzQgLf?UIf~I@F9;`ugjV@_oX5GYGL{tpb=Iv+vY;m^ zM0xOPjh$eAut6Lws7CpV#pp{7jveM~)%lDf`KRDZ7LE{_W6!Q=HZ*tpi$$-&&irPT zf4`q(GT5x2{OVuS8A#iGd6^M!i#b1kz$~y<3UH#7Et8 zGRKzC8zvXa%+m^m{zzS`5A1kX*J>2bwtfTWBPQLa+Gv?V?`wksh`n<#xDfC`SduwM z?eQ@A92E1Lm~GA5!ABgGBXAlhj%Y@?TQv{!S{d86sMMw<6e^SvO6zlXzGv;*up|>) zmwT-6mCu=9zE|gN+&l(Zn>AiyoM>9sU!z=_^vO<=exZL>!o$C zfan)+L<$EB9&Nw_YmADrqwBwA(_E@z!g#X81#xI&%QE@=2ddU zbw4=#VZz*sMZb(A#uia^i12U%okn=8?b8TAls^vGeAwuIG?>Gp(&s-gS4KTV>LEK0 zw{HBa#(C2nzLv)^Cl&SXRukZxwzt?6{N;W*`?q8+^94~8n3AG8U7J_1_ZEF*H`*P` zNy-;4pt9iZ?fy-x_bJghb2h~0D0NM9%pH+3SgEunAQ-$vSopn~Jp=ZB49PH3qq}^+ zx--I-sPxYIQ-p7J8A%15oboch#G1fWQIl=r6kg&0f~quvtFKd7WKkYlVXD4Jk?pkx z`s%?tZw;&jxDB1eLxPQ=wo9iR@pazbMk=u#3xj-7*-B}rsJN+vlN0?q+-vBLwV9CQ zIZ1bWg}}vHG%CT3MmWo;6g*HgjMO?H$_actndXMu$-KR`V|u!oJxkXx{Y4w5zSP<{ z(ftp^7||i)y0?NFbq-b$^%*TT9x_7NVHw${p#DJVJWmF8&Ko^qY@3f ziEEmM%sPjiS6`LS+&Qu3oWEW=&kQ?Pe0EfDHn&u**X#?a`IMqAX|yHqr%IBFB=m+# zpnvYMJ10k39L|q82ea!OcsLdt?9%sU>PD6VUk-g@-WQ5DxMQ3RL+iR71|~mFgt<53 zLelM07R+n(abFbTKwo{%T)7-qa9BV}jz=Q54A8P`=3%{@jJV_@57jg5qhxbgn)#Il z!6IBx3Omk!F<<}28?YE58SOSeRsyq==oDMkxt`} zhs$(T4!AMfCSQcBA^yYd)whS+RQn3wEkD24yUnw2)v*UzNQ{D?5Aw&HXX4#r?o^2e zA`Z~lueW#Ii~yiMww>gpe8_1p*q~Cu7hykoq*%HgHI)l`tqL5t1D-G&ca$CPOudJt zM^7v)g3|vOfec>XQq=1h#dGuYR7s)F?d9oa;O)&CO0PZDg$#M?a>wl>i~?;#b3Ndf z<_3ipzOXLZiP40$w=<)?=Tw8$`@~%z@1!GEyig%af}apwX-A`~gie&b1Jjv1{s zSr6oQv#K5y-E#am4H74j^uHkKrUA&8h+r9&4h(5-Hi0g=r#2U;g~lHkY<1;*KGxX( z2Bw_~WDH;4#H8RTSBkK^4|RW48nK`O9((JtEIb-QPk?@Hf9u<9RD^xX@}{rm|$8 zA1lg{z9fjF%`dYHq~vjLVEQEn5kvkyg%}r_OAmABJDMDV`JLe@s%>G-#1Et%n`wl3 zzj2o3&Z2TH0Pxu`?qJ{uST$WnsB|o}hRi#<1h6Y3t$+uMIMo-ek ziS6E4#HdAT`~m%EqoO{%ppDx4Ba%ykH$P~2b!tF=2xv}HJ5}P5ky(lBVFfkp`g>_LKnyot*qq{E-F~Xp$VXDZ98#iKh5osyF7biLT5{r}Cg5rfGT16T$?){Wt z43rcU1yuC>@!{S$%HrD=(hKLenmCQ57LJpZFz@Uph08#0wGw!Bit8?;kFS6CQ5zMh zx%OAaeV2>Up3=oxK&xc>!I^MEfWMkbUbh5!nN4!j$S9XvRaJngVp-TOqE9eRDBr-k z=gC2+`8+x)8bu9@jH=1SDLR=eY?@=GyP@XV2%)0A1WS65i)o67 znP1QJ-NJ#MaIwwjSgG1CqN;zB*Vt)su!+d+$gx`KM1Z~4RTBBFqMB*|Z;EZmUbEXM z-RDqXTSR*xqB$4A6$ztr(?=8+x6jFvZJpLbIu#aPd(r9WX}|&TA+zxMoF4TYlC{_c z2T(UV+G;?{>}|>MqFX)M#fEx_jgzcNYp1Bx5Xkl$2XQnJHILTotp#beEK!SiOhusZ z6N%A#h3B$VFG?Y>2^w5YAe*kI)orHN`cwRyRDZNFh6!Ed^x4`7rQQD-H5DV3rg`;C zLGzdC{0wZIxyY;%e4zRoM8kH1N?~@@27r&tshQ}I*g;alu4d>#%6mEc5f+{-iug1# zAJY!YFi6^ZnJIo6*;u%GP4h1!CoWVjBj_lO)~E^~hg6c}cH@F9FvHN-u9*6vZ`L2< ziBr($HTO*@;bEoxCtigJ`y}ga)_UCW3LK~?Nnxnh8IyPt9>O4X6WM39rLFd>AJC*P zq+^Qfi0X4Og3}*A>~b-SsyP!Ngz0-`$l1!YI11tjqBx7L;r9oef#85c#?{#XwTE|h zi=7lRFiINt?3$YG*gs%XyFZ_FRr9ZLaHs2MMYS0PRBItuK9;p*dz*s)$&k_D9^8lZ zA~jl?64rEuw4ap4-AaI#DO^ddJ6hn+*Duly*q0V_lL?;i&MXx>@k9IA$xwuVzg;0i z(vO`<$!e(BkGixVR<5&>m9a-k_TRkp??CxxFd~9H_&o>J6vDqipNlXx2->Xz|-Z{^4%Ye1g8Y^!#R%QU=lKR7dB@X>=xuy ze7WG-I^j;A5fF_3w3b17OB%Cu&Lmq_-OzC>yeYWTE#UFBKp(1tI(*B4U0e~Kmq2Uw zYmacPkY^Phko29NwLN{^0|XxDikA*l#!X3Q^L|*#oA2T8LBA6jdF)>Wx*jC<2ZYim zTG#J*f78kS)&8=ldz;~MGQu*BmiLx0*XcsCKu5ZnNulD^xlpZ3+BBmG~FR zIwBTPRqimSo_h!7$3+#saiTgKPxH**$U58R?@x3_J-V{g8T*gut15v8;h1ktzQR+1{H&vAU zcf(`4GR5`{KLW0kPQ;$m#zctmRK7dnR%^nZB}{>%hQ5ElG{VldntwBRXDyQziBNYA z5%-_$(qLXR@DjPm`T)NX-jUWHPEQuxnq3ymesj0lDr9XSAtjtyJBi&&x9Kmj;Mu!q zC8c-&V7!=GkxkU&qJ2BnWn^HUJ{i>b5_jRJn+ zBE+Z`uTkCBPA9DyeDK;$kvcBR!%;DnIH7~5w$*a;SsRW&ya2?}PA%@rB*r#rG&2f1 zH{x^1t&8E#-U zKSi~0oc4Qkme9#;jfIW)dn92tB|d=cpDWNVGGlP!#j#d$@zT1IUA4}Vy^X~Tb=Wh= zx-~HWu$oHP$pVNYbv1XGI1o8-k9`ZQ*s3K(LYksz%9XM(wX@kLDfnu6+{^Psuf~}e zP%7pT{t7soiSkt4vQ+CM+KtXu7E22CGA@gj9aV(lQqs{{$1Jsn^gB+s@@XIs6`k@@ zn`-4R$|pK`eh$6zp$_jbm`LL`X_3VG@kQF)YQZ_lWCKN2klOBhFKng;<^?Yf zTBWIC)*ZhypQMB|N=;wP+466NFj_{})FaC&Oq)k`Hy~Fc5E)!E8|2o4Df!>swXrxP z%$m`Enl2Xl%}iYH$#ROh^nY2T*pJJ(lZD3oeF8q*(!r*ct(!vcegW!{%R}Eq`vgE`&)=$4ew1M;7g|oujo;SbWq5 z18UPQ%Lr-YaR-q=F5UID_9q26N2gc5q4s8D5c_m;A!Ir;UKnt$Qj#2JbN%T{jX1;L z$5X!*s|gBrY3aLvHGl>74Pf0rb(V46q)yf|i2;fOHDc-jsnsqk`F!e64#MN~SM34g zMgbQ&It#CD?6EAIfHFtrm%!|1CYJ@+_HP1`=0-v{2AKY%Et3&u0Zb>Hd=A99i=~rQ zhZi=E4jnEfp>i$RFV9mI{zGd~yquzL5y?8$bgn`VULiPDs0!4%tP@&P>LbB!ji(Qt z4*-VuP)uzvBB{{SGJa;o;F2xZP!SuObnZQ28Vr!9jc)GTg1Z}DRM@|y7W>xAYz%Q5 z{TI;f#A5zjCfl-KWp01qY2AI^w(r(o?Z%hH?-kBLi<$ZPcD(j>*fYb+yWf&gMOL?; zx&ixmO*~5r%1(J8zN=So1RqA58<_}SdS;UE;ldhoJ6NiMclAqsg1 zQ>2etdyIlJAVC%txL78{a9GGeALSs3g1jFa^~5(wkdHG9JrY{w=}O2$(0Ce73v`IM z^~yTe1#zJx^q=dQRuy1W0L8Yf%&~^QO3xFOMk*G=oyZ`n{y?jYfHK>hAb9 zX=N%}peH(VKB1<48Kr3AyeM!9PWzf&ZoHjZMw&()nCv>dhm;}D0y(Ta_H8(>UF0;2 z+toyjZQCfrxju!FXZOW?s(_sZqtax$LK*R+9syK=0t&yEavaB^4egP}E{)Q<}F)DPne%4;h!i%^gmRle_v_D>U z%?doxj_CmmI{M4TA<%dkNF%v?|85nw`W$}2^;eOZl67*)ofpH?T`xUQp7sS{``=Ko zSTu7fmQ&YOFU9r2+^{BV96d~K+=-_k66%SmP? zGZKmg|CM|}u6>3;zwJuOR@21J&=l)kM;b4W{QJN-g@}e4i_Wz(Gwd%f>-JSP1DK-%giA2!24dVZ1{nA9JMch;QK!r%`Mf9asP7CM=X?K8I5)ezp( zR6`zPeOa-%&Jicjwfwz=uLT(%!q_>`ObXb?3Bn?vb1qemOSqcW$+<=}ytT8py5*0G z?zq@n(g?O?@?7L`ix?&NC(7m1-Le%(jS_6+W)!MRr3X(4;Gin1$@48|(}(FY7LXw! zcZ_kE230g)jiU`EA>~?cSx@5TREWv`=1hx0N1P43V{Jf*yBo|V0GCr;|HVYj74p|? z%17S*lIo&fb~AIKOn^g;$ku1mU0Ks0NAP$)dXuZL}Daq%5QJE-ZRoO zzsmj7qmA8RF}XQSw5jl+N~S%YCB@SjVuT%m6FLyHTP4BV+NLNYPN6J2#~Wl{y+5!q zIy}sYXf#10hVz=qYo7mv;|W;0_ZBm_f$f~Cc1HO|WGM{7#4v2QIaK~AjJ47eRU}ln zUk6cw!26@9j!CMEc|2vBN9JQDvQ?UBbbZ@p&|wr$FjqWbdF+6m z?^7;9mQ0SBb3yjV!6P-$r3%K=UW&dtP? zsyqsX3E+>$=(gTm*3A5g?!m8X0ha+!VJ9GK2I(T_hLlzaB>DtkM}NeN3v?B45+d*= zZ0)PO4*eKk2kdSiOBJ17)J{KdOYCOhj_nn^clBD{@0t}qU&(yJp4$LgMhgYs>+xJ5 zaQ&`3_aoyYGxa^-ub(lzU>ERmD8H)vAB6&-`RdcIFz`#UH&a#F;=+FWOR)Naq1a6Y zS1K2odXx1%@s#(gx2a}M_eovm`SB(83XmSh)uONLfv+*H|D7Nau@Ks@HQ+6@i_o7H}_A7(jNxHA;&sC;;L);kfL)~G0=im1LIQk z{my1^H%34a<1K6Hi4mCizAHXDElI`_?l@}$0mfFqCzLA~EjmRu1~A8+=AmJ&Y4ZH^ zlP>6YLN&zV7K<`f^U4P&GN8dPKn(<7j6$iOXaux-;QDb}zdsmaGJxT4#dY%h#9nOX zn=Z14;#_=qkEwN?9I4 zLOYNl+Lb*V*Dj}?WA<$QeF!mma-9s=l;#Rg zZV2QkkxB7(+w0f$Gci9IUkL!3j0`R1eiDH7F2ABmLs|y8TY)@^4~i;7CLj5yqtd}0 zMot7ttDu~KB0A@8w~yrs`$rK1XDh%44t0mi>%jC<6$)5I5I+S0PMDT_yVYg}Xenx8fxT&!a7f1ArHt_<8kVIc;%`&^ zuzH7*$@1-SQSG==-X%7pI53#^6ERV4KgB6|PT-<0y%wlEk2qmi;q-y)(Ev_b;TsvP zMY4E^BD(yCY+LAiGSuJxXRs5u_dRCK#W{<#n7u<+;Cmxwb+7rWs<1~E&?|;JTr(h2 zCe^t&)u+#DnP45Q5uo#RI+f#ImS5W z^?ZdZ!+}|5;|5PhN^tM`mJ8M`I*ez+!rgSS3zt7YFzN)oDAl?uDz13U;%cS22^b9RUtCN)f4J5&B1C}je0a)Ep9>7za-^d` zM{;bldzG_{_ca-P#Fq4h@Z3U%#cGjt_1WfrQo8Ha~cv@>_b6o?*@qW8L*6oQi7pHz7ilkw?u5We^WJ_n^u8mG8hnL4F2DV*mo=Jt=f9*Q{2FpvKNl=-_WRC-g|L1Ot+EoIY6-i~G`jcRSp12RSsJ1)W_bkOWk}|l_emZDq zJ-_~r7gGQP)qIG=ArEqijAnD2Qab4cv81tyM+y~>v2weS&>Dc1CFG zg=ny6mqsBRBZSoPttL0TWZ3w=Ih2d8C-nvpQoC1iuW6$eaCVaL1Vjfzq{0$Dp`5^As{3u(>f8&6W zRRrfwyWLuf`&HEP^XNY1JQS|ol^D0(o^cVSpyJw?+KuA0+Y=ctp`ax65qc$0^fyvS zI&!s=a^seq@V3Er=KL39M;HTkHvbers!emVCW1J8jB!O<+O zV-6;eKSGcUUIQIXD8lTHf3DD*tqauw1CCQ)_v29{Nbe6wekXOP^{MTE;?u+Z$gnbt zM#SB`@)FE8g^{b{9wHz263k6J(#}dJjkPcD&Id6jQOY_-&Z;afN-`7N5RNwJn|8Ux zC{e*;|HK}Mf$pPj6jXM=NK3h~)L03%!(b^858ZW`>gVDuK@FwDAW*7Rb4zcT)i_Y- zk0C+She3t7+6JC6mnud~=GydgYyg%vY8>B|nTqQdgegzEhlcD5%q|od!eAtnBI^MQ z-IP`9TyLN#?pCUIB2_wu+Nf-=T1397oWV@dgl;SCAGIj3gBEB(*O^Qc374#RLfXpt%MeSKpS09L$5v=g5@a>B7!_zn8cGbC9nRVFsHC zX&k9Wq`9OvImIJ?=GocZk#jZ&&-X@vLhP3Y-BL*vlfZdGAaclsoi+6i3s-0#b z?A?w*rR}z#t(*dQij4UCDTQZN=L<=YRByEs&!bU&vX-^O>32Fb&>UEm)@VH<*Ab$Y z1_eba(&_KtI}G4FgR3^E^@DLS(wyS>C~L*;?sYr4$ENmKoGIwiC>n&03Mf#3kl66l zgAX1!GbeI?&xzwb2n()>QO7{o8aX_83ka9T7RONu`ye>^@6~>`59e4l2}P}%ZqF&j z5DLn4q8a;c4oN``e?&z=?O5J$2XWIJ^NQ-&nv;sW43VHbv<}&FwF-_)_{WV$IXCi) zum9y5!j=qu`AKD!i)M? z@eQuaDGM^7Ti2#GwPdsMy4Qr=a;ZAsFK>P}u)-F6-|H*in_71$I248hYKHhNTxArf z{cP!BwBkHt7TZNA2J$1w!tptsvs>6QGL}Yi@|Xu)Xp1SI;??D?kFODzdFsF%%PRJ3 zq_I(G0Ih*#o}w(CYlaN03_&l^5{?Mhw(Ht%t`6$T{3KYDZ4Yx{aONyZO(!cax{wi+ z0v@Dzm+{!BDqNXsG*J$qEw83+h<;<4&OfG7L=7C}n-RMA$|>!~j@Bav{W5zV$%vVgmM@1T6V<&%E2Qtc&;==3>B z(M70wtBmtXA2J9LrBrE#nRN=-7Sh3{U)jU$=tboq;H7FN>9-NU>R3?}s}0g_4k^Fx z%G}(=yFURfXq1bZvIUmvV_xSp!5conj6Km42~V$;0|z2m`&~Vs!MJHwm7A--hiCRX z8%Y(3-9L1aOH4^}7?aEw6(x3AlAk+)?F(McKl*7wtCduRuNAQZhQ9tft%^hU!mLk6 zdb(gP)CFt5M+K1qBl8vnoIgrqJH4X{{{9Wg4Y$xWo``wvgvEwoax*Ef1dEoJe}!2} z;}CPJ2BW;WHXGd1#U9nILuyJioFJd{ydt@)T>5sg+d1)=`Wz>PQVYRt$V`ogA z<#i~nUIk`YelN|fu4wgBzAFtC*5}m%Fa^%RB+RwG;3DA6*xT2fAKsjt-3el5msfl} z6LrVgjbCL7V9d67Hqa=D5D+9=wVaDs+&h4a*`JddXtHLr45TtcghmTFFdT2O&{`rJ zNor$;Bwj{Eus7~=wq%-Hw8Yj{j@RaHtM)HmZ#c(A4^{hk_WxVVr)*+ z-(mVOPvTXlA;>^=x`ITf83W_=w3Y86OC7+WIp~cKR1@MK8bq0$M_ffFG{r9oC{GWH z)ri0OqgyoQVlIxDfnOgWzUYKBm~Q*hi{2sh@v_-uP9CC6^I^k*cX?P(m{m-HQntca73 zR?pRefd=LD> zz5J(o>eHVAJv2=B1?T{KSoSuJ(e*XQMeeH8qVj^yA4FpLMFL$$($#r)@$g9z_a$QA z-lwT%2UX`I@d(nlc=mek_rkW(gP+nC3es-#M%woBZbj02bidM3A=e7vyxWF5h`slK zTQg6GbKoAoq|<}IsHbqw%gK3xagpKpGs=@+oChiRUK5__pr~bVgg$)k{!MRFbg5~s zD4T+1zry6`PcG^37>9^BkZL2NX#-UdgKO* z#x>rITPv9$SwHjpT%$FhHAo+MYX{eO2KmMbWxBm3|FGHi-e%EeR5CB3yR~NMxMaLY z+rL~>E3c3r51F*6Dzd0plrmsoX{{iMN!1h1D@&(xc z2Ux!V$N#`r05;D5f&WDKZ)7Fr|AhE&XeDM&B2M=I##UnH`U1@Vy@y5OYdiM;QDFJn zj{ScWSiZJn{~ra`FLLbvqrmz_j{ScWSii`zbEa<1)&+}qIF>@1faxkYdo`Jf6v9teYtqbx$Q!M{?8It9TH%BVN87Nt5>0eMK zaE`BQfFTG9a4v4nRO4F+A}~&-)LnN-Oh9MdZe0q^_et}99|6nq@x2ZPsy2JlY!@Mb zE3gy7&xmY@f-VtC+$`bW3;$w)4Rea=&>n-^w=r?k#Kq0h%1QyMyrdzmr{E;L~`&x37Jw+%dv0Wb%PgY21G8;UZ)#&bV;6&FmjCT0~A6)YRwk&QP2hd*OrfMezixa3)+M)R;^$ z!|0VvNVsD-xN&w;EAS;?SbsZ;$mgPe=vWy&W>{kS595_YOE7*4<}q=h#0J4mVzn^I&D2@xH95;HBh zAWbtvJ387?nZ?>ddxhGXAGH6g;5a@qWOWAyIR`Erl-z~k4`NV{r7&m4V=7>Pvt|gA zSj2|itHNsOfjiGSCyDSfg6bs>mLR0Np~Pt=9RRa`jVo#$Iec;)U786}Pl`}0x$-?l z`jfzzC^ATzz>{v#I~t3Q7zWa~ipc^O2MPtB$;$}Qv^nQo6V*sdpRI_&KZY=KC-D$2 z4fN+g_M=jL@Gm$P3>Lo?c3S{ywL&e%t4FK2aRJsw-qujv>Jp{3AOi~np7q{l!BII8>1KXJDS>`CXTI?adB3^RanMKQ6C{<-vx z#eNJQSGieUANWXrzlHyZ1{?FTD{O~8Bxx>Ml@yjgt1M6v8B+9|PZF<3rV=`{mbvqf zj#IdWk=4|2K%|Y|a)4~!ggJXSZnI-H?tRdpTE`%{I$lyX-c1l6j;2_H@fS%sY7Lk+ zz~7{&s;1=i`{0|5Cjb=J>VDVVoi{((pL{B6+IsVTI;ZF-&s!?%A1)>V43!-j7^~AD zPip=v*unw_Ty*HK2d&`kD0;Q0=sWU%N3($PbtlLEyY=th@F$d1lhj1&k*iVqHb82V^cwFtW}0~(8-ALU zb6P`mit2!e7>~qn)FZOhRrfwR-fDAKXTMBExRO-;twUQ~HcZv=Bg3wynyK{;`jN^T ze>29v74ls-Xr?txK!P`{)gpDM6ymdIi+3Ojq4+Wgv=xfOvQW{2+oI5ntNRa_B!wE> zFcCLy{tX82WndxkE})9o`)QBdrtEobs|K)CzPcR`(9moYUz|eCO4&4)_&)$~K#srj zdeKaZc}f=2qqoJh%unjC7>{Nrtt#XX!AR2A1&!5U5JvGWbx77aPkGD|($UA1%TR+- znRKVKT3aExdyLG-1R^!LJB(iv zAWEfq)Rdh@4kp-)q$zIl=9(+6)`289Ub(|C`sqn`gaY!GVW_mTnp5^VOxnnRK<*!t z?&v2VH8JDTPmfoBdR){a8ABxFH?dTYagY%r&D}&yfDHrNL`=w|wX=H>llKpZ$=f}N zDTFm*vdae5Jv%5Cnce*1sXC?9gsT6U8(xFG9~I)Fu!*3dCc-b z!(^!ZyTgQ3kBZdCG2P^|>#GvGr^kTxJ<)^wq9g)xC>W4k!6^X=Dzn@ox!)Z67N6)} z7XTGE{X!ytQKxr5Lis)Ej`EYQ4V8AtPeCjLr7Z$`)M}u#L2^#!G*B8b(#WA>D{GPi z4U?AAaUUKXy9-s6y(snX%ar?xZZFbo&6NAu^?F3}bkHI<1u=tpbl4Qc=rBfzO}RQ9 zQU$YWfHs4B82FwV>tc8i>!RB)*3tRdeXQ$rH%<(HLn@a}-r&)6%BT#=c7$dFTcVh@ z(ZfHNmy4$0ll*q+;^KjSNB<-K-IMP8J4!CSc~lzVPN7twBOn!qN=pg$(gTrLOB(V6 zrA?3^a5q$13209alvc*@V24V}NZ0>VCEWAKb^q>pBprmVOuO%QJ!kK^XWzdA2H49z zy^P;~yC)sV?&qFLue)cLdd4pGj9uy(O?O@LARRO>ud2K1?rOTL9nsBE!v;E!rT`8$ z(r|ACaX60V+71rna?IQU-k81{pomE9ECu&o-$5J*NsS1}1eMO&R*KL$yU zS@Rq4GM)0H)Hd)I?dY8H9^ybqV^;rkw4Eq_nvy_GUoU}9VXP~N10mTFA$4cDE}a}% zMj07>^M?A&DzzO@heqzVV-Jq6=y2UL>%bZ)E3kVUQ59LG;6dvhseDmh7S$~Ow%>OE z-`8M1aQY_7qC!MYOJ_$B+-ea6h4s5m(~7dW0o(miU(V_U)jjh?^QHJUCN{7VRXv1% zO$zcio2niw=@=#Kst@xof1v1*AsuXwT=580HrhrWkV{KV#UheIkKNS%QCm_Eiyitx za(FV-mtLK3Et9ih(nvtLHABZXAQvF+=UW@K3*Ybo(4xMEuZ&~(h-Q47}7539(dcJ&n zc8U(!*Cec^-D8Z-K3`q{qwddNy{qmAdF3W zE!eaBrnDemr>&>&rUQ>r(7_#c;QT6|meu9bwiZ=#;?y`5v}-)lS1N0t=yEE5)0>pY zu6^Roi~1%ntF+rmay8%z=dXB7W(NB%sww2sa?=NmTZ5kFovm~ubnsRKta(oMqWDry ziubQh9+2N2YEp`5NziXs4rTcK$Y>U$gsHsYyqcXN#M%s^^%EWv>_= zl6Oa6KW2DZaAn|zW@&iRaqHld-XkJ9?oCj{Vv&0(g)xs?o=ksN)^^wWFR`$vC^n9+ zSo#TzRsMfovHt=UWq!h!A&CMLm+%Y)DYqf)0bBu>cT55empxtu9Ji+J0RaI4IF}#D z11Xm>9|Jy@5AOjH0yi_4BJTmk0Xdf+$O9>tG9Lpzmrw8k5dk-sA@2c_m-FxeGnejl z0u7hk9SI1xJMjTLTLL#Wm(d*w6t|5`0_+?DH#wK_3;4zdw>FQlu=~r@HQYO&tGhLVczUp4x4fNTS{RASKj>3+rPaV6TC6e zl)tw8-Rs})-yoM4@W6*Ye}DhxGn6OxkNOLnJHX%YG$zH`!j%@jJoO*cUJmUZqhD4APVl|a*9a~n`Zl|*6uaIc@@Rd=x|aI4&Xo+!S*fCy$$Sq% ztg*I$=Xi@x>KF-l^!h8}Nbtb9EA6!A`n=7UaooDL`WxTTDE=Y2e}XNYcoy>afB);B z54#xM25F~Vj2Wl)#M+cPfwX)gs4Xhx&gw`Ddx%L5wP0rCCKsLkat8YcwXI_h*`Xce ziRvr-Ri&bF!wim80vl)i;MC~P64ItT>;=y8)xBtAw=qrct!8aACb=S%(k^X@R?TuF zn9^i-wTHoO4)`Q?e=d*HC)tm)K$m-PV{_{Y2hG$9H^wdb<=)5oN%|Ua8`xCW)&UMkN!%cU z={R8Lx-znLq{OgYtPHNZx#QpZ8|tAmrmx*4v6+VZ34z8r7B-IP*91Aiw(hL3UMKB9 zyBSyP^4@PYB*m{^|KqnS4*OzFlASq>=Nso7rv?Nd9nt)1MD zVK(%bP3|KcH0>+%o{v-2N_q_chxBYB3!RBN+w~OkW%#-Hrp`=ikbTLe&kNG?x;c?j_m=x9!O*0$8HGTXu@XPW@j}#H{$EH9CU@h8E{GBnQbuda;^p~9!ufoM zFAHHV7OP63VE2v1a(fY`J!``Fck?|y1zi!fJHsYw36Ya^S}R?Of` ze{!=c$!Qg{lEtC~W9DN+8#2Pgws)6m)W&TOS&j7TztUkZN4h9kmxJm8ehW~R8DO)y zFO!b>$t;k!y|`;?mcRY>&Bk~)nK#>>y`BuNC-Y(R!7nHK$NDGXAO7_>{KJH#B_Sy^ z4@wd8zt>hHyJ9ucyh}Z@yj;Q_wiNXWf3D{OeGlbGs|?X1r>zK`^#bNX zZ%e4l_V!!{SfvB(*L6UIA~r$u;m#86o6i&LiYc-=+?t|d!;GIfSbcfq7_I*^8Ue~V z4f>q2Mp!SvJJ`&geqsUM$1SFO5P=%*x;%%wpV-Qk;_)RofW%DtN^D}S+e|(Ee`3rV zO>e;zO$##_72IgXyhjI+-NM1{Ph~Wg-DC+MO9#96Sf7fkrGYClWu0EywZelEsinG$ zMe%`iTDzW{eZLp)E6v;h4jm^Wa!PG-TP{<4hT3d5_c>y7-eSx%vC;>Nyd?y}(J#3b zEA_SBsNB^TsQdsN@&o<-C!8M;Num{*k?m<|CQ@Rzp6 zvw&YFZ{QGo;}fm(4>4Px;Wfauoy<$CVLke>k~!Ds(1WexlrDLLlwUcBf4+=v>e`@(kY&BaAV9TF(Vv(g&E&snAcl5~Ub8C&3_=0F>sQ-bGX%!e&iRDlJN>yA8=vgV#+IUk2DC&3T*&9e#kEWq;!MlD zY?Q~ye;tDI6?LwTlU(2pUTtCt&<-oBUJzz`IOWR3R`K+V+cAwKf4ya?_8DcfGil>o zDKTpyxS?=|i3|4dlIv3V5lh$| zve|q{uXrwn#+EFXlc;iu4xqV1;-@`n*+omg$YeDS(z`iK<{lDqb})G8oS7;H@Cj7` zkU3<$*3k({5`2}ZM$Q&Fd&sGEyDX4usR~qDpphYa*Eofef8cd;FRP$>Rv1Q4M=FAe zR*P)Rdte)~k`$MXI-I2@ECz4iqjUoANX(p`iV9|q2b7vhx{@gA8ri}iN?}O9wPb_$ z^Uk-C*xgYxlBA^{Lp!_48N-$X=}*gqM7)!()}rZjBT%}N_*N6Znw?kwfa zmS9@$%AK=hVN0dyw2>haK`{J$dNQge_|fS(pzxu#3`YrGiIk7UrH!f>;HgSxq`0&v zEH2Jn^4qzUxHz|fopjqV`K@@kSAigEx{@SRLWjw3e^$nl~Z0Evt)lxUi$}@8j-G$MSCd=`-|w_ z^CVS*_7X(x@`%x|R!;Pn5GQfQujaWOMG>gX^Ra%EsHMs}Y}tadrp`$?#7a4izgj7d zbB3z+f3aoN)U@2*qzZLqc4b**OjRfNhN~%02v&X&&EF<*qBt`qcHg>hVni)zOhPC0 zw#yYw7zOtgsh)*`^0~wg5Dqw5*3O$k6GtTdA)~QZ3K=^XopotE2?21O+FVmIavoo) zDH$=vDi4UOI8jTIIO%*NVY1c{@%&z0OwdoDe*!`equi@W0SwudF5$$|sq&2c>Feru zpGx#O%5VK2Du4dX*`)=s@S+^({$s?K3R>;C9MId5pIjAB_u0Q%Wn|$pGYl&AOX-@v zPNH}p5=@&!^HO1J4;yGL-IJGT9GoizGMqhfU2kj*+de9D6PM+bGjF-B-I6OnN0szN ze|4bgIm_S&^=PiP*JgjNPHHO90*4afMu`O(jC_pZ8_!$53LwW@nNpz814nL_{i!Dtb3n-RX3`*BNIPp!`I-iuSI`hl*vn` zP1h9UT@^AFPSx`-jYyJ?WxsatsuAJKe++mz#l0_1v{_wzAdP}gd--@z22PiY5*+3@ zUY{V!Y6LyTU0;WmYA{KPGY}4 zUfefSzFDKCft{=CA>F=p0?9@)mpKznw~ydm-oiS>^XR z3<_Vc*S+t!apeztzS>il^9JSxkY+&G{(w-(%Sr6VIxop-zZkmPCAKm9f7#Pa4{_sY z0Tdkp7QfKu)a$4gkXCngdBUAVcdQ`x#od5Ygb6{RCdm(hs40xfD=bJAbNd;JV6q6|(e+yuUh zHjOxxKgUOTa>;qo`heTje<|=FG!L~OIat|miG=7$L2!D#aJEycosE8jJ0v!o6lH8Y_iDs$DONk@&DJvF!%ZR$ny)ly@N9364z=dmj`{mB$cFeVbvLN@X}%C z&kdX(W?4^@?1kUs2(`meUzi*wr$vG&Gp^HD#Icrio=>*a_$}C7Uw0Rd7=6XThD%gF zzMp3W*j6;8e|(?34IEiT%T}fXQGL-4OI!#k@oW3r@!Q3Q!VX)AehyhZe`#T#>?qZmt7-=`9k!t*hRKzD!$J7^ z%DziO(ndQ}@g1k__1qW8QDZmPcaLgu_mIEN0@>bnf01Lxs_r~hnhoOlrU_CAYu6V? zAd?d(D0_S^V{rYh42H49y1{ju|ND*p_b=*BZLP4Jb{^_>{TSLAmQ}i?)fUY@((-6j z5aue=SN|?Gu-KwUNcEJma;;so-oq-%(V~kXZlb{0>=H9>zlixN@)4eN^U%%NIqYMs z(pQGIe~nNNq8@3?lZtJl64Gtt*9Q7X(#tk^m4PrXZf`x;d*5RG0v&JbZnkU=J2a)5 zR$ChL7K8dakAtDso2|`ZmEg^XTCpruF@05sm2Z}z1h%~`?CQNh`t1@J&EcSpvMR@# zbC#oeg-R{(f26)h&Eo%Q1`5zTtf)KSlIK2gXhpr>P~`CQlmIt zs02>d00KbVvbFO!AY`c*b2P!qXY4s+!9`It%icOr|5rY^s8do^kBG!owLs zJogagTHI4spVH{3UpN@m0Z-{?(+b_}e|;wzmvD*4Q`eCZqCiGw$A!3hbTXu z<8jUBfG4$Aa5eaIFbA^q4PSA&&BW+nZ0?#nXZS@e;hIsHP`2id7P*ZMeF8XwuPgr)a`MGOB4;G$cE-# z-^H}4evhbcs(revFBgh*ia0EtTKlZY!#%uM4cPRdHSgM_$%<^X!+RVn`288}`u4cr zqP2QST=Gt^|Hz!U_&v!&k|Q#8S-kFww_*J>+aYjj47ma>nsDqKpzL9Bf7eyryV|*) z;~_&H0rl;wSZ0r_y#9WT=h~Rc-*9#@jrPoOjdM6dm~&KL8cCDebddE-*m~}F3b3*{ z-BdQ~V)J;o^qIuDmg)-Mj4LYZp0bWgmw$&DQ+}*U$Pc#$WbSQDqbH6RO1(4k^H!mwzQaIJX6JY5O$LDix)hfbT&LVpSbSbOeheujB1L@3 z)82k3G5G_Oz)?Y*%K8t$p|BrICV$Y2879ukV5twj>Rl(=-7LJSJvo}#xpCARJU80L> z54^nsfA)J5Jz5Bcf2r=moa$PBG_N>zDrrwjJ#m zmth?P6PK5s0x1MFGch-lku4X0vK+aQ{(QwVIkCZ7AaO_Zz6ka__C~C+7ClL(R+e0u z`t}8oNFZ@l)g#B?aJm~uBJT^Jc>Bkjc>C|)MEU#q=F(86G%3k9*=TpxB{d+_QZHbRa0`c;cJ}kzZDW)yVWQhOpRUNpxhzY61lJ)j!I2SR-xbgaO{P+R;lIqC1u6M#0%uGp z&$BwD;yNGc7PR zfVr@xgBwfp6RmJQ&F#4(Z@Iix|L1dAyHX8`} zB%-X(K;PsuKl#bBNpbY4XO24aQ~Vx3+dCMe*{I(W6pag#D$?p_Xt8Hk8quGat-oLy z8{*#s~wYUcVgu-x^QiO2ANno!%ny@iZ=08+|om# zyYn_X1`Ip6;0`-=yMa>~*jt%urz4PXA_1GuRsdw@0pr zWUf;8fj*!oW6Er?xS~fmcE96Gn_uo4l2oSRT46yaWcDAMbpTF zUZ)?-xVu}(F3f0`d}Z8WWOu+XfB*f=YJ!dI3(!x2GR64ilxS$3vi+3*J?D21M^G?g zKD)-=mRP5HG#S^H>=&Ghp8_3iccQ5}Y!SbIpPpC&9AI=0J~;}TO_Vr54oLdT?`M=y zDxTPXZz!?Z#2r@l-1+5ir)X6%K9S%?w36F}h@==Ju_Xlp49#5boMpjj4kPlIs!QA~ zmxH9En5=x^ZZ{OMrEHpT$iP&6Gma#aq^#?2i@U|WxW-#K=|UC^t{VHC%2mY##CG}SB){@5Wl z@8>bb#JSZ){AoxBM|#CSIyxM>iNeqL*jGMViQN@5mW_+LKzYka{st$hsAhxiPIRTr zH5_qxKZQ9XYsCX5&JsQ9zQ}WyO?D>85!?5Y0v6<`V66-U#zWI6$Zo6zv$9@+PBxvy^h69AO6ORZN+k+_pTPdn7HnR+y2}a8}$- z*yN#@^W&$cU#j{aHg5@rE=K=oQJrnB?^k6)!EKHGbQgz@RE;Q&27(LTimH$uAzY?m zj~w}Q2yif{W&9=|Qc&E}(*;Lx?5SsepU|X;Km(=Dhzd{wcU*%fT??!oqG_D`gZ@vG ztG9?uN#)?lIdRG$pU{l^Rvv6cH^`Elb$0mW}N2*zJe5!|4E=RAVn z{+Sp&H5J;JLkHVY@WR{F77i05&u+?p{Qeb`ueyJ2WFi3$=X5{wJYvv6rE-(HI<0wI}|G!kf{W^c?=0ot=-S5XSfqa->%EWGKq!1D&S! zYa2`IX&yJjW}-;IH@;4ClUAdDb%|F|S@Km|ZK(W#Rv2rlOP?nLs!jublwae`7zoLr zIs#od#9F0_8jLhW^_?T;Cz%S(TvD=6S(2Gj#gnrl$BKPo_-LfORp}AotkNS#qTzV> zj-C$GZzi3QzpW_-9P`1LNHhhm8EjJ)B+u;A`)#ehaES7>TEj20gzfZy*#mm^s3vwS z=T*yU7Nr{F-^sC)?!ofP<$#gHP&&nXHw)2AxoX{;?-fn0Jd9bY1ZBfzBrA4VCO7(Y zw-QKs$Ic?;b$%__wEhszbSJ&g`zd)N9rRO@-q-fZ=MVZ2anS*-m0|M%$=X(Homj{- zCU>Hyt2vT;!c^C+&S)ur2=VI*NgYA@4bs*oPs>Bd0ne9ll{WGK7*KtVV{L4XO9mWg z&Ub!F*NAghdL5MDmP z!>m0z7Tx4g@S3v%sIZ!yubitVwW_Pa4t3utVO^v{`$ZsFN3&{w8jfr>ZE%Takj4UJ z`!)xGcu?+%%Th4NiU|0mnu$h+cr|Ei7`05=nUuQJrt;O2C6lM?=Nuq8*(dY!>nO$d#9E1sto&_l}fIT=Cl4IQjffFg`+6X*NXQ0{Ry{Y6_2cW zspv86R*^1fUC}XrO0f-W^p?u8J`UYlwGL! zFg(M$3v_Sfmnf=Mr{U^?YP3hSDjOK4oCh!`!d&Hn`*^#5p|0YE$=}Keu^pV)ZL<=E zRJiugsk9DRxOS?i>mf^=GDBLMM{iav3oKhl74-m^!L;BvU3FiyGc|9tXqJ=;b#PWG z&^#oCVhAnMbr7Mp)|ciWT{@7;Ie4ZXSMprj(YTu5?@m9rOz3UP1kEEInfVoXYa7Q{ zSGpM?UC}gu`o6yDH(vZ#UDr}v&WzR`zv)m>^Q%NqTCwYnG5%J9ETbz*y8&QCsD#+; zzS5rZRcdZHiINLAVQc~IYAkvDRK2S}&FJ7@UV=LE46Z;t(?a>_?bo@WAA7;GW;*kncKf|$km-EMO9kI$0VD>BA-DVT8SMJn~^J9T!g)Ws@~ z+o%}FLQ4y8fBgzDM0+U6LgDyk!-nBy8Z_`Yh!aq9J#jDNL=D@{U)MaF4rHC~vQ- zEj4HAxjR=jJxPp~5mT={Wo|vY9f4z4{v`r`IOwRW1am4pa*}-c*F}Qa9mcAWijbvo ztl>5quH~YVjR%$+2SkcP%Er;qEF2yky}eWEkTR|nU|MTb>baw$cviJh9`4<2k=7m% zCV1DyU}6??Bkh8?%*7VL>X?3w^OZiMB462W<748lW7~C^6J{^EF=(e1s;rEs?xoRx zo}K)o&omUswu(gse@NR{^3`{_@<=5HqVice^_nFDN?vixFVY>>+G*d~ z=`y7ntl!*+7?nyZ(6~h)kL%QWaSX_7Ya6s`V^FI_XY7vGDim(3%bbdB?V8CSt{c3|hD#B@j3$4W4d3|osXH@EXai!O1rLY!6EwZY1^bd_&1->I zS304&rI!p?_N@LHOundEHQji1agT{Dj1dosPWiqI3e_)HwPg%tAauxoy=t?OHX2nw z(gS^A*HMO!Fm*_Jev#1>|41{&pYX{Uzj7FeL$hlkS6W5*ORXaK{ZpFIU7HP4pN@Yt zlg^5rJ7)-@Gvth%p?^2>ab_U!cX+*DU77K6#?2YWl_PYmI`a{EGm#U`3#uhk@yqQ1 zTIj>89{8&s3n`;(2mO?P>mG|Z+B(mh)pF=O(gc#~oIWPav7gZ#M`cWbqA1J|9FL^|e4%D$v=H?|E@Z>iNk zY1@X`lWmjK>vzYtiD|vgwmEmlwmE;>wmE;@&B$~R$#);69UrtG_X^fr%zkdkMo+-#Vl4W2kY{V(-e8(=@{miVtc|{o z(Ywqmb(2)h_GA}-V?<4jF}-#tsO$A&4H8gizgSeY)9bHRt5vVA39F2lvcA|-V{5(| zsIQ3WbaIL|yY3naFVwL1hii@cpH;*C>`4v#91DNDR>Luba>k77aW$-zzM+P3)GaYp z%3S(oO7l)xHMNN6B?i~Cj5~L8hqrsW>*RUS8+Z2?ZxgM50lf6fKLfB`dq<$`;aboC zO2uMnqxtsk)XP1mop4tw7X898u1EiR-r4r-X2ox zj(W8Ou<`eUI)oagT>AS)#8}mvewMtrN#qV~-N;$%<^YgB1}^p8r}SWhdhiS4yRzkY z!`UrwIM)<^(u?1#_Lp~`-M#`z7sc)P+DyG9i|dcgPK#TVxKHk1yA~nJv$oxJy+ZC5 zc{eS_G649Gs$l?`KYBcAI5tNZt?y= z>-*_+*yM)en%fo_*EM@CZU#7>VWNIpbnS=M1ALu-#En+c`TGd*-P0&;OEL~Pf7?ja z(4ifNcOmZ3!xHlg;>wU-Vo+Dfah|hp56Ikd?}F>z>^VJnn5s8nI#h7m*0Nx`j#bwC z7tdon+V28^dbo#x=4QRtP=~@yDWU?O6?v5H-UiR?`J@` zZYIE{CBJkoSfEQzZyl|>eR>4tDnbu{Ll=NWe~yu2tEQkC2_%DHBaND9Z|a`90l%DIj|Q9>)Irc&>2t&B#;o! z1QPuU5;d5vmu?PyFD`;`eWLEN$6~i|9ciq1K)XW<*mZqk|0Z?`&|_*TK$9nqVrR5} zr6ly`|Ema;JV%9}e(@owaDaB*d9EIUQtI&DjwrwgbTYWNj@+g6rDP)&YcSR9;p-eX zO0srjiZJvn94e=#_-e*;s_NOlyEHydiKEBc-77C^hW`2iD5*>gMXL^>J5${iwU2f7 z3$E@SDYbjuOun;O0B_&FRau;Ut{nwev&z{Nzw>hzeDN``_nXB#*=dD41IYBn( zkM0$;WxId%izt3#bW2C992Kcb`OIf7Jrl+Wl9 zLGAjAlj#1m2%;)t$1b2O%8{}(vUe9ixcoa^%XrZK!33Nw|$lX8{V-XL?Afh?##A%$9GAPLX6>k9R~_(KIfR27z*Go+>|*G)*z zidb>=tcdVORH1w#J;5qErwgOvv8S|87x?j7B8}*brw?cOVILl=e~E>D;nxL~_h;pS z+*ge+?~&8s!*rxu*+b81ALk)Wi`D7#1AP{ir&7Yfr?jRxxud^)?(5KM_$MoFUaH;v zOD?yrL0%N#&%;TdA1GsxUx-3_KQ>6{W+YhvxP07IAJVA-NsB;y)eaD?M6_F};o|V3 zT`Nc!{@zXa{^Pg*2XwEoKbK)00~42_It3{NIW#sgmr=|OW^B% zr~D*@6Y0}D3xA;%e2@DlJa_P^K7IV%x4(f7r0sPet=Y6RZ4buh)^=#4yU<>3-be=h z_*>}t-LTJ~ws4x1dQDxL7nq>T6Z!aFNBOjWd(BU9^5*5E^7zXOPX40`*oOZ2o*pI) zH~13_2{& zL0lKaip|0!2J(k-FV=3V!O!FGhGe0g-1KREh<}m~La(`lneX6wgU~OuAMmMWq*RDY zRU7HV;R;Rk(PUt&nhPxTr)-7UgpVC6La3H!z$yfPF#HjL`Ow|2N^LgAwxx`i%q%8M zPnxiK%Nm)`kF;{LGH{SF{YdM8v+zkz=tlw)73cxY>Q$}n4=w!}zJP3n99c1?(3PKX-y3a9$`zSw-;Z$`)# zc{?S}^eg4yH(O+rO!zRnP{z*|i&;RCININz=~_-~+MBjF?LG$mRBdD%u7%nDYuYoF zyd-k4v0euH#>l1my*If6!*r1YLO<7UWPfFo9@(W1WW$vXRN%fq2Qr`o z1kgjh0`3>giqtX@Hn);&B_~=?;go#w)k~LCO1p`|O~+f5blyxcgrMh4k^Nm@L~ z1{kUe?I^AqxzH~psFrOTstoCv&oyH^>CIZ#dUKk6p6v7fZ>OO{cRcVk)6U8;@P8G~ zTT#%`j(>>tidEI$P`TjRQ2@30{3y7 zRfczWw)5N-MQB$K_3@|S1_7gD)38A*0JQ_y&{wJD=5_u4KaW*#iLz4j*;HF$ATFPG z0VdKvE;5g0ZPp=CWPY!;IYY&zNq>bVQw8jF_RC50zZhbEk2XLeS!xFjPsWVP?#|?% z+22li*~8FMoClz-#p2BGUt6d zR^rWukLpee8@uw3fl6T8VI>>c?}{SeZ`dp7rLey_8Vfn#d1N#Ay7#{MlEdC6|I zHQimjJ+ff)=-kPgHkXQVB9+WN!>;VoPzIi-dTx6!U7|If=&I6_x>~G=S6VFnqW7It zvnj%g2<=QoPh0k-pD=T%xua8mC>A7<=qYLiHnTu!T6K-y$;x)=gnzBFh;JG5HEwD@ z$GL4O_LVQvIzi1$(5fx?xx2R7ZtzlB+c)W`mlRRN|7q3*Zfw^~1-%SlajG)>=lg=b zX+d&-fYtE}#kllfN{LfPJ7;}wTp(h@zv9*YPCs3WC3SAbzZ?+~T(-T1YZDFq$_X_{^tH4u8>GSKOyosES>mF+v3N!g)Y?t0w9+$)QQP198XD(45SqB;01C zf2-3@`Atj7TA6w6v;dPkaFB`DPP;8A%R#;d87t+ZoOti7-(0lqG#TqEjQ!0-gLaZO z_RgG?2%CtqKc}(YpkQxC(@tr3NRHNAX&_K{LI$~f-FSi~z<&xjKH6Wt8+L}?*{DyL zmq|U`om)c`d9_*DVD-1ciXnX|U|l+J!hZaeL133|(d%FtNYKy`K$tBm%~eo%4o`#B zibMF#?+YH~?rIX_1&?BjI^3O2G+U60Lp^5@)0>SJVCB0=(*c%r?#TC{>}G=EP??0S z=!1ab>QviN34haF3{PT5&G00QPa^2oavc8w3Kro^5(GbH(#CE$!DE=QjAa>_9jKLS{@8J=X$(7*~Xj{RaB{2DL91&6cMq z7d>eOZhE?8Nv1c4=B|{r<6C}lAPl#ufK69Vc_Nx|pMSbwPFO-)QPV&_HF*sTQ%PgG z#@{6!(A1}NkWlh^q>NyDrgBxf(i76fII*Np9RXOV@NIbCNXy~{_{8l`a8>r-8!YVa z)QSnc*Vq2&W!|CQoqTK}IbkGn9rhT)F(3+iq|Oqm$Knq8laVbBZfZDMquH-mE3>#Z zidoGeCVydVU`}51p^`G-{Y=5pE^JbtW;t}y@Z~*Lt2P$XJDGtTzrQ_u*2Umcq*gBD1JShnbsS_ zra*yWAV?HS%``-*H>G_$_an}8Ed9=}iVwbceSgY~z2QOY#L2GRnss=C)6uZGnZXl8?Z;bq-#LFpIBXJlsFDDSHe*@_L4)5y~Vf%y|x?#H?P%? zwSTgD(VW|RPy0!oVnsWFx#8&dhFu|Whh93p}!$|_h0Oz42Ng*l<-Du?z0OF6Pd-1fD~ zbEWr-PEYUNh_qOseTRIh#=#`gl6ecJ5P!17uB?NiUTW&}rNaWMxqWNN?C)KAp6S=) zNw%(R-!nVh7glTrwK1S{>BCAM2|7C*@|9!OljKKb9VjY}L5y`oh5QwTdj&CZ7&+Lg zS}};RYN$W}39H-H+tb8Y$U3b?H>2fbk<3y$(FIx$@*l_U01L>bK?-2zJIKTd;D0pi zNRGRThhG>24mwAXbRy+D#z2IgO}w$rI@&EtcVnGlLxI|0yX$1omq0h0aJE6DwMPbiNvs&tiUG#ze7Hd?VE=8A*ina8E=CLHkwa<4 zMqAR{mCIUaku5p0zAJ_&R;c3Ug@3Ib$s-$I5zi)0*`_koY%{%mZ(59pY&+bj3FW^fo`*`xPc&l@oWo6Yj ziS4|@J3In}ibtVRO?t*76hGr6Yo=kQdY5$9(_ylbe}CQ!-8{c;Dr0da?c%_{ z9PX7P)_ds`$SlNwz7cf1;2|x=G;gn@L1_$pX$CoCHz0e_D`ha3)PJn88w?(T@zsn^ zy;k&C7)%gPwWWklk|A{`XU|yJdaQwI${tu@#vU$6hh(T@S2K3zpi8yP&iLCo z_eh1~q{0z#Qz6IF4z=(Q{wiE%A*SZ?hEF>5p$(K33~c}~HGf%4brtF)v-JBN5r_#P znooO@&#$F{T@^S;?eps!v4CHrIM5_^uH~kbZC9k`n`!bLmQMJQudaS=%w8u;TuI{E zv6k8@J>)H0tH3fiYW%Aa5*&Pjl9S5iKH zTPX)k3sxVrP!1jt0BAs$zhS7gLkA|pMmaUhd~oG>N5_BA8!rXO9H&^@6Hf<5{R1k> zLQ|Y#L7~H_e?aF5pMk0nlgC^Oa(*2CLelC@g}}$3QxJTAFvzOfDgX7I@{fP}@vrZ| zihlg@zyB~vJ_e+5Ldk)p=W*;D1QXCKN8Nvp17*@~(e^w0>D_zn(idM+xi4~(F%3fF zqyyN#B|(2!=<#>~N=l?WMZw~Q3~;QfqiKp@gDJO?0S>z4W=*q()8rFvaJx3kI6=P! zT>98Y|HX8$3Pwo1IKMO-ph)ZOX*P0fvI0?>2I$X|JPbfIYE$)O%FYel$#|>;MXQOi zzopC#NjY0BM=OWM_2*i*x=j zrfJ4lbZLF^DAJQ!(pM6(tvMrRwcHX;skqj2-6K2atYvd%jo9W3f46jZoP#PRJ}Da| zR+ryQ`G(owSWfMUZfi{@qIvG*D=DUoRDH;KrXoA)two9RvfSnqX#kAy+QBT zNf1k?zOdjJrZ=^7nV5_qTZ6GJF&H(eIkp;Ly719;S{$&jvF37C@@bh)^O)h^O z8ybB{z)7qJ4YgFyl@{jifupM;MRwCV^3hB-W>n<0 zMKu;PTNZR01*)Dvmcd6|jvp!09(bWArvvBoba<*Qy;2UGtGZN1`ZjeP?(d;Z-#K(R zPOpTAfiKQsSLv(sL6{cAKzemcj23@bw*)_CE=1UM4ShWwi8EgMW*3;3NthB(CF}mA z`m)O)e?$;W2wXE)jE7fE)60i(US$B$=&!JSQGyPu4TW~^O`M9DnH^jMHIWc`n;O_& z(RH$4hMUqMi%<-Dwkd&OstEho=q(DhvP#lx7^CJO)APa7rywJPnjj+tD&c?FAft%O zc=C4AlT&mc#_5^X7*-D}MOOClVhGu&s-v1EaiqL8=O}4hi>nXX*k+{Ut3Os24Un6{ zJ&!t*l#AM;F=DeQpA8t|c1c^rh@E$yG<~sx2BT={Wd}9bhPBU*6dP z$ftZXH+KNCDxqY52V8MCG>m^vIFQrhm3n>GFmp7sA0#Eis$LHhI+G#E(ihKa=$n;J zz*n$_4QjHcSfs+F1czw+%91KnN~GZ+(@|Iu{P;ZZ%GF)Q-0Vx?3ZG*iG(b zWoOP~RIQZey?mIQq)FMM-GL3F>R?JXM7t1G58865c~m_}*HTK#BX@VzVL{G&*8M~} zTTHOkd;#Xt8KBT04zPc*{gQ0P1Q9|EY$dZKo1NWkyHDq`nX*dso!xDa1W^g-?d}Vt z1)0o_8e}e;gWuYICZZXvSz+S|2lCx}E&YV(3*!`#G^vGRMwD%heiX_lbW1Ket2aTY zK*b}j`n8mGd|-1Q9oTC~r!~;b?7#vp&1`072OvChhy|+yObCD3^dl!H))n29)1qKz ztH47a7}SDmZ>BSK$`!xXHD;UCouRvMz23t3*q7T}baxgTY&ak)b!V})$K#{!=4$I; zwh(lGwJ#ip5l<_gmaVEtQ))rK^iSsWvleb^U@CfwyS_~WtD(DYJ-1h%SaIt~KA6e2 z1O+Uh&sJ_SE-8NrSl=N)qPsH}O2Ox3Rx^7t$4^s!*J+ z`|eE@$-Sw%+Zi@9A@8=fRH2AyvM8qH}lwJ#&S+yBpgLNkp z&BCE`Q+0=R!GL@^+h0S>^Cg2Iov{X*JM)}2HN=hWhzuP!bJg8gcUIC;-4urGsqTzW zs6;8eG%u*7l99k?@U{kpvS&?wR(P?JYY;xGRioTyIQnM%NNdt%abQxpm0gF0L=%Ow zk;zoCY{Gw{ftLx}U7?HdVYvt2jBkQ#%rX*)IY(t*R&b5gnqs_(Y;?Q%TgV225&9Oc zVGdENGp@(?$YJ~KCYmalGjH_I>b}Fm62$$NkqOKkln~d)<^^}xnDi7H#7uHBl-HYc zcJTm6^Y-E~T%jX_oE^hOy+cN-k&ByS=@>4mQ|*87aP25R^_(;{zKsY(b&PFmH|wb& zyN*`!iBAgWNc8D6xSCYXkpU#R;vl(@-lT*MpxK>JX5Zp)rB8Q#x~p7Oq?plA9dFAQ z8TE74kCx2I2^)W!bAbim?3rOJ9rgj#W<<7QI&G@E}(4mQ>~k9-r)lCXhM2QT?-CP~=RfaZ_A z7ywy1K7n3UDccQQXQ&QpnY8ss>vR5>g+Rv91F#H~xwGAk0C5o;I{E3x{~2#_gO@10 zVS^hGPN4eS+29ynm%&|Z@S&j%yE5D)G(6YryzLX(RRIF9j@(JWRF}bw>I-9tm34nM zR-#ORIjM%KCj}BB2p!ZV`1s6TWqDE(3d?PJuU8dG{&weJ_h1)HDwvFJc%;&?lJcAD zJ@wjVFq$t(BK53d@2#YJt)6Npufprp!Vq*E4^s=2k4qMYvUq5!S-kZ- zHqD+{?n`F*sV0BFbO9BOmB%s1ZvKDy-!T~<)ge5_UH3ap##fj;h#ayR?ETeL28F)j z-OsW;KqjM|rPGn370)YX%GvICnP6eJjpi9RJ>~{LT$shU$PM`0S0SR#QPy##W&>Q) zvDRk?2e38_YIh2qA7S<606<~QMl{BxvP)q}(7Ld?0FF({C4~r`hcIP68OHH*bjf+0ZE!m`nnif5R~N1pgv6UeJsh(rlU!9ay-;%MT70h zO&VBlS2r^n`*`q}D3-!#w#!+w>D}DA*H;+p+2|=+^A!JDKBPW@d}aCrk{x* zbif^D24*6NzrB}Z9eXzM%$;M96Mr{)Hm&AE>tD1Ae|<3Q`YJdcj?h#G1l zkdQXRiP~0UdYBa=o0&}=b&2TI-TonE^vDkTbP!8gWF?CcheHWgxik=VHST@GGa=ozI!qXPZ0yV ztf6O#O$HrLkxYVeCVHN(fu0D~%Pe05FFo-6fnA*<4x|t^m`Ej5#XY$Pj09LX?|q!b zg6P1rc{k94jMu7o2QBDNz&ioE1G^A=N>RxS1~M0W8qW_jP!q9-W!B$JiFBt(ONkS) z2c|~iFBQt?Vh?{0DLL#2<*ZrDuLv73NgA6Hel5QO^Zr7M^=X0yI@1(~nrB!zA|ksP zyHxxJs|(`QDwuF+tX#d#6^pvH(^*P^!E@`nrKL}kib{qeb8J@Q4M>^&xok8ZTcEP{psXC=U^Zt?4*kl~&~Jd`3?HV2GA zh8tx{C@WCvn`KHcOGVjur%VYBO<8rPP6?aMVx1BOvsR}B54~BTZ`3Iv2WoV8>Xfu| zS*uf0Lw$eAVTN&HBXB_F?_ds{_5$qAKIZx&R67u%frHGCcN(>MX*twHIe-l1I2 z=es!evP!w$WS#NDqJ3GdI9#u_GdG6{kE003k%j7tms1pvmw;LdLGIPQRnyri7qBzR zLF(Ytm4(#?04-FD_M!cuQ!DO!b+{UXQOVi@-P}gM9qu z@B%lA-lD$1JJT}B+8ql+TN7_P(Y(+3VML9o#GJe)x*8@~SdxrGZo(2@Qlc1dbJbC? znat8@Z8{duK-TW1_LzMXPG~#I5VTpMsQZ7=R^fMm=x{0&9av$OooO3&zA_-)-4pA= z=3y_%i)WmKI<*`xQ*F{PUMl?8 z-MiU^p(l_J@7}{Mo|Y5VgrZz^Ym^QA7p>K0n6cg z=iYW@0184Z|Hp?rUx2ujRf_QJcV)75(k#}Re8gw`i_gUVqD9kfcSlq5y zWi#sQ?RuSjY?|#;I|ZDZoGE`JL!(Hk0|s3LIf1afPcjQYg;c5PgN3B48`)~qMs{V{ zUPagWTGPLP?u%C=FYgttp!PI!BNwisgYDU?yhTqh?-)&eJy$hXcFv=p>w%sskYCO9 zKJPMEECl0b)tbx>Ltp{`iej*Bz4A+kAwd6g$m03RcdykgbL-!cT55kooTy6bO*#Lz zLlBoofsT_z!)sgLa%>2d6QML4_)O`-!@Q^f)F5-M3w7xh>Q|Hd+9c(yFpz(kC;*XI zR@2Lp0)WSp_zJEl0D6<~h(S#hfGFrHmJX@RENbBXwppr)gclL(-bk7D*NT9bniBIE z$V|Y4LM^EqHlyZ7?6w)ygjaZt7CYaAlQQzaneQz~ zKySXkvmjV*^=d)-d@^cESE&1#x$lM9gw(gz&=Ks>0KTv%}pmX^9FAx9r)xUi8{B6377cU_5m~?WC7wj_-WdV4flg&-Mzj%di z@D60EEnZ77MTaPT*pvyq3jwW=`@NOM;x}<|CndkyDP(`Za=k{(e*B~*?#%+%i%*9{ zETIHb&M@s=UPX)dUc?df#rvHo5bSbKIarLt+~4QCb$`mg)kZ#$#hOl3MRs z!A0NR_pyINw}qI~dl!p${8}v@%?@lpis?{r&xgwQa`ay8z31wFm*-A&XklLL%y1f2 z&$RJb!^+p##~fnvrvN0wP##}>D_YJ_*kP-4PuORkg?p*^O_{f=z8y2HZ(TlJ{oSDl zthZlXQM`0wIr|U-^C6Ux&|e)w%|B(|ffmenU`~I&gV7oLSbPVX^;=_^?nf0*by%_< zN8g0z)0i03@RqAf1DQ**F?|9o)6AR7oHkWK%yGt|o@{qh8FR@I50q8pZkSziRHkZg zvyD{yzhWNs9d)G=CgRZ=CL}81P|8-l@YN!8+FbpT5d6GT8l^>gnfO5}`Cd;D7qKj$ zH8p=a)3;F_snlc01^dg;GhNd+g`TI+Fa{h|EKqft06j6!haPZ@v+(J<{8z{Y?$5pP z;`XNUe(9?HI_1ceaWlHFuefiwaUHI|uz9(n@^Wv9Rm{qGnerU1t0ns04&yo42kZA8T!M^XlF58ig5g7>`ei1`U@#avgW~1yFXH9*Uqt=;_S2Ui zKa6~l@`%<-|MJs+e39@*yvUbe5253W_x4cQy!`ab%by-XxHlne5JHF7uTlt+9>HI& ze}qu*%Duxscx>Rei?3S3d+%PqYH#b8#+9c!f00_%-yg4k`RNZ|%Gm$?_X@sJ+H0z=lP zAMpKe>%aH(Ho#kJOK;ZU_g=lK+)kw@e?Co8mDW}kbQpk0ec<=%qaueQEdRzYaP-n+ z8a2&B*EZGwG85KQ_og;Z9eRO)l;_yMwQdqh(whQIdlG8LvZ3H3y(zsxuX(f%O!_{L z@mBt2M7OsIsd?fJp=pvC*8F|xHKXOdz^$;4x=>|a*dJ|eO&{HxPGh3bSfZYhe>RLc zLeNMXgyg;&=_>+8IxsTSRmkXZm3|UR-|%gDQYRA&@_LU6Xau}W6~9bhxw?3Lo$0t~ zl4-s1i_~+TVZ%fy_^yBiB=1g!1(4K9Uvb1DzE!$*n?^^NJ4x;5$-l2l*=93a(z1_? zHe?^+UaBC!6Z%#ky%Vj@=pox6f3KjTD_7tQe4_Y>(CCb2v^t_{{DkgCBVq-?(4Clf zLm*_L${s79_Z?IjlA0hzsR1bsF#>laOi5LS15d*PSCs(aR3Ef-k+({FnuhkS4qLZk z>Kf?{x1KC?m(|S~!Kff4Z$srU(3$ zX4HrJ7|}!r$GxK8DyZLPYm*Rb=e$MxZ!%Je5e2foBMOa` zt`wt>+9H(Jc~SD0nuroxL26PWB51a6``SB2dmZn0Wi0vD`c*^+m~4CPe8pnLAohfF zj@ZA=n-<}(+?_JTclxy%f8<(4?TNkCg*ZWi`>eD>*_ko&j@at3uBe5M3&c004iOI_ z8&@&kYO^38xaj!HzY{i+01jaQxB;ENZ%7gN1Zgizw>KgR-sm_;ksS_f=YQMLrWKc8 zI*7+0nW$9C9Z6sfIJG(vUBv?#9=j+*Q#M^6O(cv{o&2d>DtPh}e>@pUafJ#C6_h1$aiBh_T`fV^9(Pvz}YfGmK_=mY*r;hWlmkS<2&! ze8Hy;r2K1~Y5x13*ad!(j4!K-k*EtT)He*@o8F4Fb4j*Xe_MOiy7a1Wvs+Xt(hg84 zvkirQKBr``d89C_Pdw_3AEd&x9BqdUGOja)N@Z=<*oqo)izW2>kXB7KPbsSa@>Bo? zVvZ5j#kCeq8b?xuIV3_5HToFG zi4>~aVN1W*mQrh-R+aii2)#D0nPH~L%zgMO?-?TUe`39_ybcse9CShovjsNsP^JrK zN$B#eQ+1g$K;w4oR8Gbp1mjRypC7lYI%(Ra=h>F( z-=h9pzC~99%BJRcbClm!KJ)$x^NT15W!xg|?YbG(DhG zYfXu%fBkB^NuSIo?n2GIXLgXkT&N9svvR!)=y9TV;Vfi4Kt?rt#E(wBkhVKP>1G1u{n%Fb*z;?tY55z5o?#C~SNzVpv+# z+)Xj(0by>cs77@-P^{=|zI*$=Hi75K>JOGSe}O>`3B5S!k6>eI@^fu6$C(!4u*RQo zhHAN)cy+Fz)#3tzF5#xY&D__hJgVc(XmOh+y zd6XDjX(DQqg$)m!!kZJ0#vNX8a<#(|Yw3TI?C|m&nP7SM3=`Dm2+niF;Rdr}O0Py7 zAY-A42XoqRESNawoAz+h@lpOPl>Pn^HVb5~)f~1tx;2;)TAql#M<=P*ys2JMf1YBB zf}xmtAj>ug3r=S%=mrOr zusTLrKFZ_!ugd!!f0E*`e__O5)l5eu8_@oM_*mqytNSHH?FYxU5&ImCc~qUc95Fgr za|+Jd#ie}EpuaoE;NNMj2FMfa3!503mAAB31IDUKqbT43`j*xTnwJe{#44JAU|8Y- zl4g1LDFs6-4QuW>TCPbmNe`8nG$@+N$vdQ(q=(R&kMjCGOh9i)e-ljo!x%kcCy7qy zMUBuYMrK}hpJQ@wcAUAIwNNq*5Pv6UyNC?q;YrC6K&ub~MmLfpZT6_=7+o;*C#{ncohwW$;P_d2nyvJQ*S6~p)fcQ@8wqHhV);JtB*!tV zom$;tV_WSc8$O?|*12g({Y;#Ppp{aTpRn_QFH|lXtQ7dr`mJw!TbA8JP?;G)9NTzXb zljDw|n{pU?tTP)u;6`4iubHTipzJ&~!AycUJdkh4RL%T^=8B*9ROuIUGjbBEw0FcH zLKJy&tHUM!z@8FXJM=w`4)aOyyPiaWFk;lbnsfM_f347kGLj9Lj$ns_1$3uj$iX`L zHSRQym!6)0m>AO{fXI53^L@29O^{&h#IxashC9t1)QWo7Fh`q=vUbHWj%Wnsh&pbl zruq}s-odlG;d6?)kf10!hMSFa(IOru2Hqq|7qycvTA9OuVLvQHVJumr_-$t@TCKDO z>a=2Mf1rA%7EsDP=jk?|4P|;n!yEb}83d)TDV;f(yEIJBW9Fng3DKN-*fL+=Xmo8z zj47!H^>mJFZCglj(RUAxwLXv>+xwEk-kC{H48CSMr9aBjYAW-E-pa^5L%?CS50bdo zQZU^nl*Dt9mmTlbzeJ7J(Co!^`k}G@h?WH;e^E|RmARzXoN^!(W;TqcwlF;$-%+)s z_tm(7(x2r5$=MtgpU+OIHR3Qbj40^&Lz+kp6x^9JdZKVlkYaY3tkqQMGOkU#rIfMH z^%N|=3afm-{{-++4Wlv&PA5?UcUH^Y943!7d4p2@fzB9FaIDqr;Cbxv4 zitg|#j9Bh=?o1Gk311j+Ai@g|iRkfQBI-Cj-gCuG^~`70alFjCSm;CpL!VKbHis}w zJKK3a(8azqwB|1NPdV9BT0(k6!QI;bf9|mQG{GSRK&Le0e>@?sZJ9uEuOIzn>MH5( zBw7m+|DU4USb2!3pFy{=@o-6{<@h!{HIalg>8Y^F34i=ZiEOhtlRRt^l-eK8_2c38 z^+w>xq%vU-uM*F8=qdWi1d<&;5ik3wq;7S#@wY^qqod1f6`B)d|IE<$z3job^6;jCatU) zF<8W=JDuG*?d^<@GnQ`e?Sjv1EUC4jG-K$(v2pUfdE7%IQOUIb!&31SG&fCOkDOn2i>8KC6{J9ze948I0ZHIcqobQw?~k ztUujpK`SFn1J_agfW3C(!J4z19d^Tb;xF=pHC3Br!LjMt!FZ1Otaw^^Gu2C@ITts$ z&bUs#1;ggPUGP*Z2Pn(~f309v$|i9PSic5Flt%IXUgDUD2dIGKqTHlot&-zZKQk>2 zdS)Wy*{oK2gv|l$35bo1qoHKHSmP5JM|($^M_R*UY@tU7Hp;E>DQSLK_3IoFkRv&D zMtcvFzLkb*fSFjS_$a@*PK1kKNLV`uY(7fLM>D}MMu`_j0_ZV^f377HHo2}LW?v3# z@$>gzwcI46MtEk1k+%7$G96GzyM?yeN^3Hf2;acK2TBTBt(D+cq1-%byQmG2`S4r?GY2*;D#eX=D```QxM0*Pmx;u|uI z`%+$?pl6!e3>1n&f5(7lJ|%|Gd6I^^yLVuG`{vjjP4FJ@sW>Wu7RzjKsZj6OLd?j$d~^Qcg+=vIz2 zEi<}RH%+d+&m!e3(DmGAkpa(5Y$qiZ`+Gb$rtC4#N4e&?e~E#r1zgvz?SV8mLI>$t zhr`r55*v{W>YZUN6B!31LK3kuR}Un#8&Yr)0j4wb7ZNYjM15XTnSj zsC1@Bt&YIyR*hrkXV9fO2aRV-H5JF|Im{*!%!(v|ZiCrGf+;_FG9f_6b$XsXtWop9 z7DtY>$dMlq%m?T{cTRAmqdg#(`6yIp(<^5{uz|PQe?+CMg1vY`#L`{cR=DsP^}O>g zrG`sRN?W4{@Rwms4!L_)5#Z066Tz09gDGvAO+}s z*3XEC-AN$$G+BpJI$DNPq8ljUwH)5q@E+$6ccKf`G|g6e>AfYAUE5SXTeMFsdrGa; z+B~!Df5@h!0mIvmks#&5P4BpJG}2stJ;9KqPf6t*jt#mcn5n>39m-VbHn0uTIr05PDk0C4=zs@Peb_ zyFXrUcQB39ju^0q_QDEZSEljAj*$2#cNOl9@a(T*s;j@E^# ze?vFS!)sWgl7`~SuZv`lYjGA15fsPYHGek=ahc@FD*e0>O6JgBkGSTuu<;P71&$$1cAK@1F88jCYjH34n5u2D=Et9z;08Cg~nTq zC&?=9%{W-k=0Bwbm4Z2{m$e+T9J^Nte`_8sITq`kmK)@u2>g9Q+`kq#dT29c%k(}_QK-}Ovr@t8D$O+|xj8K-;f}9b#IbaM zIGO4qJ}yj4mJck#LNn1))17@f!>gqjbDddbY%QMLzRIgCq3GmyhMo60zdZ#ke-(1D zjbWGcJZbnSd&4fuoPy6=CRT z!S9im?u6eYT$J=(2JAofNAW>!k3)a-Rc4vI=YyB>Qiqqfba-io8s45H?4J(1e6$vn z)t^$H3aqy!dpqnl<0P}aWX<7~Jk<#lLze!vT9$J2JnL)2cBBNgY#cmOe~O4Fd8qHx zjm|wfP zdYI@=pjeT83j=OWW|Pok4u#OCLe3;pZ-cn3cv-oIOB@4~UWnSxPF=uDcNw-b3P@h6LydRqU za9#H+h9e}NJsV|Fz(hFE0(F)UI>=i^^`y#vD>llXg)*0p5v>%!=Er5fVeF+K9Y`T) zDG$(h@8u~QP*_hi#

dD!^{S+?pA(1+Mp%xztWgd{U-paRhmme<|bf?VU^k%+juQ zB1M4|N;(c7ed#62(A<;hJ^FU-ms6`6O;O7cu3Jtvb7)(fZFB@4-}NPL<& zG$VS@Xo6*_&h3C>e_)azgs1msxZI!Ny5vW=X+5SwTVUw0nY2B(C?jlqF8eo`d^Z$d zzxr(9g?^*lYjYE|G=NF5G&?8VGeY*c z_n=)RwWrN=m;MvdL!WanjBvM(6GWNyBSq_Li*2rc_Bhi8=yd&b!DL-zUZ3QqT(VB* zQG6+ADBZo1f1?(7kLD2LRfhZuk02jICCQ*xXy(V9Ly7RbJN(*3x^WQt3m;y$5(fwR z^=>S8Oi&DLH>3sQz(ErYvf$qNo+u7wOQFx3#U-PIe~n`nBH>GT)ynq0`cUn1^IA-4jl8lVz@3Bb{LRSbkywZ{pe|k*L4(Age}H} zcjD480iG&@p&jfz!O|Q)-Hjbmh~X9kPl3)e|vVPedPd{#S=F6JZI zbgI{Ee>{acgU!Xy-Ob!wK#G-d0(SEYg|Lb}1Xisge7;%*aP6oZoA9OpuM3AsM9jcv z9;y%)stmpNi(TR?P9+RNTvd4saf+^gs(JCG`7dE(i(cvQoG#;UCB(2oOd&jPc&8k( zC{FO)iP)#Jjw$i3~w2I4)f5#N_I=we;MA=9Xg2<4kq_o3^Co{?`OEUJExj) zQKm~Z^8YgWdv`=(CVi$XZoQA@X$PGNkKmsa9@ZXO4CvmaTPD}Yi5#+ZlJ$yn^@v+F z)fou4YN|7`x>r+O(!%YxYN|`%Wg;vCx>`SG#nss*t?iU;`;L@8tY@joWoYd@z~Wr* ze>3q)tqvO;oy0Z+JY~NEqMXWi+}u&IjLzpeIi~o@^JS)eEezAXt2y_*1kJBAM%$U? z-~IIEzX%niA|(bP{r6wK{OK?7;;-=U4==!~VtDyS{`8lZgd7hl(tp1E@yovqUFeJ- zn?>_gA2y#t66-zy46tHF>QKkaU$liD7VltTRI4yJa`r)&37*7BO= z0OGw{>8yg;yKx+P>e3YBhPb(C*~FC_Vs(Qkz0;uoD$dfiqqLT@cq>k?*>wsP%H}NX zH{i`K1g-bHp5oBw7C3LAm8wfmo{~+Cj(TgzzYrWpWPJIprQlbtxTE3Pw83ff6Rm1!uF|@#!cF z$>O(%0{smB1m#cl#hiXgbuL5-d9efipgE@l0HX7hu{ysMGrzGFBTZH|nT%Aw4F4A9`Tm{e7)NST=H z1@>ekXe1)ra#+xXMGvn#cg~TC#I~tJWxiN|p+P6UI(;<%P7il?u)2lBu$goPU?2b7 zH88&18!}r1C8jMxDq9j+e+w`#wKmPXoG+dg>CUMWDKF({&`CeLT{7~_NDBfmKLHtG zTXcSJM&~4V>l?3vg5$EDIPiH{O)K3{R4f14Wz`^{BAA37hnrQ^GJv(>X@lf5@L{v4 zIu!@hW>~BXiAKZg@o}X!x{C|A_)5*SME78lcX67$t|BYt?=No-fA9tj20LE%cw(33 z4xN7CO}JW9E%s|Fje#YSbo>pwOa?-#XTTvwyRrbt_5fZIP_O?%u*cGa<^8?;Yr>ZH zmAj9pd$gY_Og(|7bdoTF4am`y-7!&}YlV08s9K=6i65+A)4yUHpv0s4ye1d%kjg2k zFl@wRfA9P-f|uqV*R`(`)`pMO1E=QKPN(vsEG7Ts{k5lTVQctq*WxOf z#+t{CG?~RHEXBpLQt{SY?NQ!g^YL0tvZf5G3^&V`rJ6ubg)FCZ<^Z?C@C<0?XfNMk zi3-J+sfE}qI(T^2<~YN0QMj3071bdu*MOS`rFDGM(^SLx9OCNTz0>)+dFx)3JA&w3 z=q(pn8Z_|#1$Vf#te0UO0~7%;moX0oC<8MxIG0h$1{Qxyk0!Tq_x%-flpt)2kKzj$ zEwJB?CxDSlVBKt=VkZI|A;=~9`>Eoy$YzuM?Z5|V_UmqvMY5_`Z;F@yd=W4I@=4^s zk6%Ci{BGq-ID%CcUViX-?FK4Hfn}e)_8X zRXV|w`mOUi!2mwNoK^(?iu_fE2ihvBG)o#yJ=%Yoru8W!fK5+mwc1|L2-#u)2 zZK>6Va-nP~2N0BfOb*yjf?!~4Z*esGJ6VnVBtq1q{A@#wJhZAbS}2Z|Ol68JOGwYlf@$Ml z$6p<`#wRM{fBa4*q>!)ti?X0sJ=~(X_+^@I&s`$5_&DvtwSImFwPIOXA3Dg2-@ff| z!Q`|nIIP$GPS7wvze_XgUK({s?Z^I&!Ipn=WL{qsO(-%jn|qxDExkS5q}OrEb1p3d z96q?QwH{bvTjI!8Rl?N#Bs1GcDYmETye(HuKO;zE!;xub#u*vZ1xl3dhewBMx-iGa z@*qM!Qb+neGQH_6H$4^9>e+kVB|BSZ2=0*hh_CYxzx|k+%(un}bp!#MjU91Ugadzk z`&c)oUv?mo+XO={uvXebSvB@7AB`zQeqVMX^0IEN;}i9$tfKNwTJu8OP?${^n2Z93 z0g>cG>9fO&{3P}6RHC1VrLl*MgP-H$4hehkMg&Z(Hk7W`gOrK5uMMdpqSQ&(FB^ho zkRIt1NQdwemyAfb#CGI|N5&;^FZO>3$Pi55#2rpaY~qgKZI6EQeFtj~sm}Y}&fq1C zh>s8loWN+r6vm(raLCA{K19eciuJStk_a^s_OK@0nU)cF*10g7Rwm(rqAXIbQMPi% z6YVD?*wDX}=5Sthy=@?sO5&$#1Rx3+GNMX5ES5uqKfE1=UZaaN_5ew9x43@>dH4RY zhSs8-FX05Oxs5W?hXa@ODL4^66E5I1h#!dTQY+p>;r`>YVH1CdEb~+>n@>#%IB=xX z)S{>_lFXQhILYYpB(>8M_tqqrBzwyu9Tk}-vp)Kgp2Y(+eKq42NpvqToH%4Cg1%u& z6?I}ONR>m^ZyhvMB5m288{vQPq-cBYZySI(ynue&HrxmTBJl^X3!FZz_j52W7?PKV z1B0wW9unj&hJ;NNHnAvHIRUq3hVmO~o7dPiOmJjR_}929tLD>~5GE;qZU4(bR3s|G zg(&er!G+kWNOBni+V1Nq(YkO*TmuHi4{FUQJkHbV0q`asG{CFwQRsg{d}&k$QL)5x zR(;Ky3JD7k#c|QpJ_D6Bd-;MobFWQBz?F!yJh4}>Pq0@_$PCb}!2d2+KqD@rdN!=U zO+3~Xxw)SYH%DXb;1Dz#?UcR4@U$0E42@63}M;? z%%L^(P5y$X_>aqhP?%BSVxT$6C@Z6IXq`KhmbZii3x~pu9oK)JxRSN^F-rw;Ai?y| z{$mX-BBO^3Xy+@b@ksOFPb+DbE2*Wzb34poyI>_K#QLDeWr-}ptr?xhqcqqH{Lu3z z;lPu(Z}Q7}N~lX&^AvJuL(8q6K@M&FVYM4qAyHLS2UR|ctzailp-B0y&{?rGnRMW- zC?XrU1&$k?xU=?>cd3KiCFZ3oZE!& z>?0h;JU@Sv&aJq#(IYoKoVjD7N5PAm=)Z1E^l%tCc28<1@#J0!$#N9)FYPS#0a2Dj z_rCLchI)n4pt5FYEVJ!=l)bo=2ewFP$n!qCsM?T{0V$%$Bo0ETb$f20%AuH}fR>2S?U)?GNTv_KG zQmY^KV{;}Kq7 z6hyTK5m3$`dgwvyyqF@1&gEYP$K50QWK^R>ZqrC#_m1-N)Btz07rx98QFLBjQ5*oE znwNj0z?GnF&iC?0e@#9;VoWidK>E>tUHh%R^9plu*_TtKIX%}BpYq7LRlgJex|aA* z0+9xpy+Wbj4%&mJgWW!fRscvWB0L3|(Kt|;K}N=wSpz)t6z~Q=tw{v%lyvghsW?3J zw0>$T9*J1$C#HfLe<1CQO+{_EkvxnG<6M6-H=T*fQdb#>;b9998J+Y~!%lV2vv$R| zIz3pj>~!JPy*iBUc#&N>`ri@_HShD@znt`|GDe!=Jx_2su4ZerMk5L7IA{B?VYHw~ zni`rAqg6Xb3)&u5oHl*!Nj4sPQsJNANgjGuU;6_d6z6(hJ}W!pz$)5kXB;?v&pCf^ zwCO5!-=?d;9$v~0(w&lolB2dBo1l=V%`N4^s%SeOSK1_OE_OK5_|lvfPUAZ5?{iOT z)N_=w{e*wpSg}1mv?u6ogO=Hg({^!^zdfZGEhZ92JMILj!lCpD+QONVCE-42k`|eS zl0D2D2y8g8-w}kSCUe0j8!!AlLKLW~8{Y%-_l@a+xD517ep%a<6)K^_Ab;CfDUIz#?DvZg0C19QG`5g$9t2NBl(1U_QnnAPUC-OF>CZT zc%GXbs*CkWR*{9fddY<-R#*&Mw`RMVWGgE>a@p`LkDZ_CC7uzG<2Jp1=i$Iw3)^mTkq0%4nY~d{z z9IAsf6j|ubmgX-P2(+dZh2W?ToGq=014v*23anE7B3>Bcr8!V$=$r6kZK~ob6m#@2 zj@-~B?kmY9!{TOqPfPV7d{-1iplrQUaHhff^*ymYu_v}|+qP{xPi)(^ZCexDww+Ay zX8-rD@94XaR(17hSKZyeb*<&os|(P}otDMjhLd?cJW22?9phbTU7y-M5DcfE&aq%k zs1*{J9jM2exN`~vj468DaW1fJT5(-eh^(pE;P;w$0Hij{&!{)?6-RGgD$xJxkexA6 zj{(=u??nC!%Rn2estW_SM>HvRp8KtVj#Ld)yOLj4B0l?+z<&CkN-r>W zxH!15oTjCVI^7Ms+?-2a=cc_-I0nw?)J?wlC>YFy$~adhV9m(EwOKh7 zL5b&lJ>jzL#jKWls4CI{Ap)yxU0S`W;99>2zqHI!oL{!n;~*zsQ?@77S&d4zeDo;I zvR(4S`1%uFB^I~UIwD9=xRX!IkAi6Bi;E^k7Edt5HYJPB|8`l;{|G?6jCfSEF*x^7) z@yeS(gyJH#FA24vw$!o-ti`wzC07$pSp{|u!0Zorfl#8Z5vE!asV&mOH*82qt4j6$ z*n&D>sR%RmdyODff!kAv71gF-%I&2|E8f4;gpA#YO(Y#N&SjBE7(m!+a{V3tCm@{H zfzFO(+9E;?)>a+zGY!l>xjbe{Tg9S)W^{sf@g-qVfT8&_sIvv1jF*5`^-+X*{um7t zAa#ZaU}p6n+|a6uH3SeRIII{?z7r3ZBf{URViz{3zLsB?EO4*#^=`cJmszRHRM$tu9wKyUKrsOadVf#3Jhmu~$hN44)+^^*J5I?vtaXozLjCD0(n)ERG7%>Was>GbI zl<_ryg4JZwCcBt|tR%c0(z=aAIzw_V%G&+*v7I;SqB9!F)f7?kQr(D6e_=KPxI_Qq z4W&h@bmb#t#Yrj=G_Fek#ffT0uD(&xnirF?h&u9j{dUjJS@zTYG!9ahEITJ{&@eh8 zcidxsNg%eqkk+)8_fMcIkT)^USyE-0(pH>UGrxNS8T>}Z_WUEXDs{xBs7OAF1o}wT zQ2%QW3fp>O4sCu%N-P8VFB_JjEzQQcu4##QDD;%vD0{MyIS2f>qa_AZtEDuw4+oJN40G3kB;1u z&Z-#dQV1dy?xKMW9A2fF+i4dS>f+10C7J@#L6uxR_1(XOHx;V*?qo&_fUQDMehl(+ z33wn1R7vJ6!VW7^AfY8Q=UCc{6A@^Vdx5|2n*27aA#Rni1b0x+(g=dI!gLSBRcp1J z(tagUQ?^!O0OVE}#4xT#_@7m$bhr(RZ0X+<`*}+&dK%HMjrZ21S#1|N+~#|oR4csLFl~A-bzLH+fy%l^{hJqr}A|4O7|+u)?vs_iH`j-+~AW z@)_#!L$_ac0JdD2HcZQHog_n}_>&yb*F+EaL`g{qmwEFWPOpunWt>Mz?mnqqa2)L_ zjBvMo??LM!^X0D%JPZC7S)<%F#=J)93N!hn3h%afRkjC)0lf8!1@FV`0bJ$HVa#u8 zDN>knR-KE#+maLr0AnhoSR=cCe~TCSk$K!BC2Q2m{aMkt&VFrN(+oF;8nAXQdNF3V zNd2Ps2wcJ(qq3#MWjwH0%Gb(mRz-)d_unO2~rcGsG+py|p}cT}{{X?iif2(U;- zFNe$Ep-Y}f0$d_HP)u%>B-slZSjmkxk+-OmxfgsA;U0=8jeoc82(*;{JphW;`&=}Z zk6nB(ZwJM;s(W-=8>3DTR(qM!_Va!@FK?IUWP5$nt|_Q^G!Td;Mm^A>puhvBV=0m& zaegX5zK(JPGDM;n;fic8Zzra8jHJ~;_Pk1%Wm>9{1I%*_`eYBI!qb?r#b@UTrRNXb z`Z*HW-i;OYyg9U2X!nZuo;w{|WRKt5+ZqWpNlIx}StIa1!IE&MtWR=d@8|j! z(=TLo34g4^8ShKX2`x4K->1sYIOw@_bsenXA}PLfbYo$k@)jul-WcUFDHe=4)t>N3 zI+hTB`8jMmZ^dpiv^3kqqChl@HJl=XS+!z;XQF%1CV=pwcb zE#S*lXxGPV9g!hC!)~JtlPxayZAgKjyqgscHhKwV9F?{-t%8_K10_dp?*}=4v{})p%5|8l6FuWo3+Pc@8?af{!yLS5Cpk;eE{wx!%v+aVV!_!VR{GulK z`oA+c@Jp-=Hr`lu*T9u0&m>;Ym(0@_tCp?D6$;%}2AiXK6s!+Rs=&-;VK)u?^Q_$d zTyAz>&*4RHCC6I@dJPieS(#eDiTc@UU4X3p!<;F%IYX@z!o^ZKGgo@`L5BP3MP<`P z%ez$(v~WA(hIJvXijp(;>!&c)lVeK5?0tl+?2*S$IjS74|>3!X~>L(pE0^3P7HNec7 zBU37x1KO1EZQy`mkgC+J|b@L$>O{ zU#D`nm+WNt4HMyq0u2K_*_h;d%im0b8m79UXN{~8h{q+BDZsbtL)|CJ?hfJeVZin5 z3K%mGsE_hnR<5HsJ6Nb`bz19Iq=39$mK{Pfmhvrf?b1^0Gtv#4PVsko%i6PX+^537 z8ro&}HZjA9igdrc?Hu3TUrSZFOh{@2ttBM_N_XNPrmj=9BV1fY5~Sc@zzT6_D6Q)g_+p#damNmwq+b2&M0oUN(MlCEMsHqqhcNJDDa*}ev8SC0<1pnAq{v|YTpv?NR&2*#|%c?H+vZ@iG_eIM^ zF_INAx{=aZ!YjJb-dkUA0KlF5E;JlDuu``lhN&`W5R^l&;NpD`TqU3;Tvw7bDY9n3 zW7O*U-}vU$Ws=U}VC!vF2EHx3K+!$I%Uo|1U7GYv54pmyXe1e3#S-nUJFBVVe5A%s z86y{RrG042Y-jCgLGDM5+y=?*`%2<2l_z$Fr=90{h4?ACC7McwB!Hv>GllZIOMLay zY|`|lsJ1@lS+?eZEWA2*j=e%fYrkZpo_h{^;|Qaia0Qi(`~l@~wdxq~_YDCw3|$MJ zycs0EK?*|na1Pz+MYqdUOpx08_a==f^3B$rC+H1Fb1-cqh$_~hpbbNXlGZL%vk1Ou z%%JnKBYw`TroQDrOMuT~@j-$7JSS8=lk*8@6964dqqU>z^J8UR?8CNN zBb7_nV3(U-@lFFt5evQjJ}Y0b)XW56wo-Ew8EO|+U1KB5m60rkG9{x0i(j?cIB6v8 z^v31Kv~3O7SnSzjruMT*RLKH&32MbxWgf*&+gZo#e;yqBLsimg+ZZD0_qHp{*O!xA zuR(V#;A9P?MgW^mKGw*3xUH$$-%jn?)o)~`Eu?9WGnU4k{_=PFceVEiTmW$52E%d&qq#NXk(;{zg0KF? zeZNR_(a6w7V~PVDV|^ zRM!MtWCoV+4lRzt-$@Ey?@Gy8cC<21;pi@=3o42@($W&(%^(XXWzZR2rl$dCPyJQa z8Rbs@WON9~66}t0k(gL6$TQ8rq$|TbAVrPEng$@c30M~cn1aj6eN_HFc$`BqYra)4(Q~q8Vox6%$Q=rlBQ&;jg?P^pt8p@{njaEZ zi2{J63CddeyRz>xFBai^n05HhDmH9a(cUIbc+x!5Q(2e&CZjWf4Y{f}NpEh7GxG02 zT0E~r95Hb+X-{1q?n+Wxi$Jqtw*xKd9Lc#8%7*v%eoqQLf%bR{#)laSFXjy!!-gX` zc*hu-`_Z!z-sUf>-v?r65vSZ7yE71H5r=?N&6`=^ID8Uk`L38&L1Q#(5;N~R^feH7 zL22i&5;l@krld+Vrb^yMk@hBh3Ed%8w}GTAyr-u#?U?5j#_MF=>{Lgg2sM9KaYfyWIiMA5i0&L1X>XMY zNMAD*N1U}8zk$NUW_ z#+i)4X}zndO)GR!&oI7Q>eB~`6|*8vCGfYEkQFc_@WUnk20)G*qDES~&P0I<%-XWy zKl!#k9<4<7eB4X40_=V`=PS~biIP@bzfRBBMdCQ!!lVjr7zqK zJb3tT(A1250_ystWnoxKUMuJ@G@F9rL}wd{a(@K>>kZSbN`W;~1A+XRRWh^_|a1{NUxMFZZ| zw~dj8T{D>_B)Sy~gpizmvz@eI3#SnMZ}J@D^f&--=pb=(W=!{Y%139-R7NqCUxNdY zBv-6jBKI08k;pp1s$+F!uL|R0AzKj%aMZWz1leJx6ew&pEy2EqA~cNKNU4twN9wf` z+lLmU(wKI>^~*lTD{Q--EIl9+1sbggb1wRD7*|*qvM#7xKdJnQQAHI|MO!hSwHGyD z+18vL9S25j!iH&Di zrwb({h^F7bU&G;$iU|;^vgmO97o}(Z?UG7p&rb$OxytOQ-rd!UJXWb|9IYNO$0)L z-InSKz)4^uQ)I+Pf{;rBgaI}h2_n-2MGn!{TS>btg#Zo?$ZfaI6+v;og&0DDayjF$ zxvjKKCQbk{DA{c!-_tKp(0)tv{ujft06V-8DtD*CU;QL%st)BXM73*_f#uF|Lg85q zTwt`T$@cD*0oM#;ayNEw)LT`tR&ntX1Yf~|PwF(Qsj~IR@drvyUTkPK4_>>gazPU$ zk_9{A9DrlWKc&D;3YjmYHF+%(!^l`ji(wtDu-z--dPJvO6|SA9+AdM5ah}^!z-BH| z{I_Ii-T%B~;O~c7jO{L4jnj>t`=_cc-1+jkfZx+AF!bS0;)K3lml?_8xiu3i(d53js(c7*P_*{>=J*MUMWgND|~?MM4a) z`nSw_^IcYhxgP|25=Ayq8n1%AN08Xd;k8ZyrFWDE-0cCCgfb-b`BdJMz4_jt16ff5 z8emS&OvC|~vlj~_R~3y=7y?6WQ3U6vrs>HAlDmmSq}^ncLXCk}u#Qu$*ZcqAyc*_E z&;UATo7yOjqIO~GZ#^KBUHgX66HlHha@Q~A&0ead_D=AG+v=@rg!RkwjMTEQeizpl zcYlS#%j()k)Lm1tyOHwfEjvI&%V{W_eZB};TO-dTAkw2`;jK7pmX(k9@7q)VD#tX;chamED#K-xf+$`V0FY!3_AaL+hQ?TM*JdBv1~Y zJr11Znqw*UGO|z>gv9q1r5;vQiyz`B5xez+Ml7(j0f=LY$|Txg<>p6{Qgq8`O_R_s z@E0SF(3~Jca!hYk@wA!90MS!g1Gs?Glz%rrUT8`RSRQ8c*$xbhw7DKXNTF(@0T-_^&1|%j zf{h}Jk2s(7xKjNVu~!)`N$qPkxrL}6BJyKatbI8@1sBbaiEufI^T5{>u3Rnl@b%im zzHnGP%{iO%!TgH(saB!;>QDTP4l=c*HK&7E1j-C94fpjw0Yw>F9lw-%GRFG!sY`>U zHiRW^MX8oCX>>;3}?ipN0q1^UU)$SWwYVIOO^t-sX-l?Rd~Xk zq_}e(#qukE$EjeLOEmor&k2xs|0EP=4{$0vC|F^-1gAp+OB^G!UufF}{(ri_YPdwV zuH{qb>+mxX&mv1WnKp&5Bu(|Phz-(wpMAv0t#xRBvd->^j2-ep08GZ|o3d`2O$6ld zN$Jod^FOs*^XWRAHMtS5TH7dHQ(os5xDrrG$=A$r1^odmh)y}CbB5D<=lwK)kbO#^ikm0cjb(=+lib; z6+knMzkyfqN&?#40n@^VDi&nHg~i3q+TF(;1D5ZF{!WQ-u9TU{tpcyPOX5J+sRbMK zbpxl&vPkD!I*L<@V1yAhf8A!QJStHEiIe#}jVsV<3OHjmq~NsN=NA~iTw;EOLLxx%NN5&U)rvyaU$0uNK!bRl!ueTLxMgs zA^mF{Ly1bcVn{z;BGW2H=Z1&}mQ z@@+&dvzOy$tV#pf#HJKjvWCoqK7~Y{zX!9MmTk3~fH}ruo(u`{frL7l_330~{9sUz zYX{*~YAjE7qc~&NhM+8DmObi$07-u{q>A8z@laX_+tohEw8EGSkV5CWQHfIx;pw%M zuMp-UGB4!_;vHRx4&MauG}@Ho`u7pdS2`@bsVq^!)B3;LAA*)LXY`K;z1}9kHoC#? z_4#A1fcB4rR=Mxbq(aC<3)SsN{0pk}CA^Q<(4Ae!@0n7*6Fz5F8jr!mouRoWm;ewk zCk3#dAyWBzu9ncYrE&Pnt87{5vE;2Y9>xA*g2uM23W6yPyMueu%qYbLy03B|t$e@buBv{yIWh|7E3xwW6ds#5Z z2cLdtF>z=)6e&^I4&@f`)zTVWgmfxKRd{I#F68DJ8MK1)i$mFkazGu&^EOI!p@z(e z9P`orLQ|M2NH1nolB`_I*lkU}L%`OHz!1wngMtSI-LVfwriwxG+M*ieLEa|!b1N5L zz-fcv>kLR@p5FcwDDbM(|L!@rs5!*XAJ3Gx?=lhKh%=e#KgW#Lp;oYLE}VQrXldH&dTZ zF*Y>O*!^Ca0)uLVd5#`K@R^up)v$91z^CcH%|&f_fWP%XlUYC|eG)?6=Z{gst6g^} zAM@pAWOhJ(!;Z?m-oWcYJ>Zpvkki|-r||A8M6-IA_LyF4vv8Q$k3>`he5|=Nh-BM{ zm9xvB^MC|C)#L2pdIf`BBYkQcCvJx&YGxt*J>S=QrkY9zH5_ke^Q+TWPo(@Bu$X5? z8l3k1v<07QD!aH3t7!QuMY?;F^d6_}tu9jDqDneBNvX=EwJd1uU4mv93roLB4$)?l zrjwmrAUb3MMgYF%n&;YChquL-dzlkuRf-=q!7tBPiJQI^8a*X+v(zFXMkYlcsGZ*Q zFMyE;3zFG^ZFL|I$HljLZo*a-5b&JWZ7m}k{mFXCenXpzIFMG?bwDuHAYsue1M0Pi zdLdkSzQZRbvH6=L=WA?k`WOOnCbW=0P|`Nw)}0x;H}HM#uK&T`fcjrM?dc&ZiiBhk6%Myb~@f zgUS6y_=oIG2q*SiJ0qyz9qWYdYPyw|XGkv3&=&Urbc^+>UObe&g1?Uf zX`k6l*D$&%mS4L>dp?!Z6HUoN#V?S;XjFN0crhSSzO0VRfd>ffk8`aI2O3@w3`H~V?A!!Kdm7Ip8WR~hSQW~X_gJ1N zbiFjk4dR{O$rA+TF9VCP_ADod0DcVzCNKR=*v{>Z04cFRk%RyOh-P|@If~J}XQwo= z@8bEhBcXh2b7lt^Qry%J)B0QpjhP7V6QJjs#Ca#B$^Zm(Y~}Mof<0BfyzCC2Z-~(% zAB+EcS^#EcXvH4`p#w@S#sk^LU?89;P$ZxeVyk*19u_9)WVwO&0w%5TletQKHCdF72$qWk5C6ye`Kxn>^T z9N|smXO_ifCb!Smre;51Zu(j#Mwa}a5P~j*KcX~-`%943%(}u?WKFHIKN;b& z;BwN)oQ)v1QOgp-l|c-IJdvs}2h6YPbWwmr&SU<`0wjs%tgVH4pg*|elSIx>Ug zeR*s4SWz@pvsq#i>Mx#1378AykO_g+U)Ky`%(v_TK@G#!bAGE5{xZ)J#8*K|`dEob zvR>keRrVM#a9xhmf%WLqCvTTJO{c|8ed32kL27A6imL9oAXu{QRtXh}XPtn7fu)8BJ`_7a8h^vVIi0s{<0SjK_rV1?zs%_lf1MIv|U*C1Jf zcFQ8EfqnZhqpdko#E9Yvmww?AkD;Nu==UiH(qooMLLg$_4p`;`>0l!4H^`=G?Vp1m z<&uEa2lbUJ0n1DufuHwlk_7@rp{%m0-}J*1N2&AA4td`8@@G!@UBJyb`r{P) zHWP-e)`bUf8u#V#;G#w3=%cLZ?FWn-hvghqjYr=&$Qe^sekz!z}JnyLH1!6G^aauEA-eG}$s1zF{Yv1nnVfKo51y`a!)y1{(47|rp3amAJ}o(wRI_i?5B3!j zk=&o{S6x4Y>4RHduQb4^5C;doR#)}lK@N^kNmIlctIIM3{b26v@S`9=-{dwh@Et)~ zAEAvJ=zDd@YndJDaF{qs5fmzOL#_0ISL^`BoDCShjg@QK?x2ImI00z{m8HLoNkSUe zb44$wD4a1fs=Cpve*`SFdPR2L3kp|14LcFGmF&%Rm3hgz!5WZMO5e&hXv%rauPSk% z&HUig9SU~a?`~M!C?G19S|XETZ#Cf%h!DdEH)C#tb9m~>XgTs!w23p{l@tUx`zV;q zr?qqTXn8MQTS^_gD@rS&U9iBUJ^Vn5wdm&im{U$2D0apB>~Oy0Ka&quZE z->vH@D;-rEQ~>-0e%NqVY_u#F!14Y z=Wu6X=g!|zE)}j+2=s^hfGnUzAPeXNT{R*pghA*EMn!lQnVYJ|=qlS;iR1TvaPao! zsXjD!ANBx7?YUCIBBF_d$S)Gc=A9i!ZWblO4XBR>{tKw#y9KB`(ndSa^NJGF4t9u3 zN(IJ^2`0f(F|7l0B3hYIVFp|OwqUlUBsi6+lI)H9QRvb$NtXp2Zjx}5_Ahv-!^V;>#taAYwJ%~pWP0i!-_@xtM$oD8Ib^SC~L+Jr1gw76J)VRc~MGF3~~e- zQQ&ujH4C#6@9_&Capj$C&3ZePKx|OR@JTy}gCwW=Pqm6~XxPB^V|=*_MCaQWt;+?G z!xG1}Wc1M#>6LhNpG-y*m0fM~;R_&{_tS3l$Ti!+G|$oPa#{}Syyg4K{Wz4sh2j(#W!f78wp<15Cwx1U;hxQ<1jvmYLs1ohZ*2~ zIqd|QNr=pk!0DhXVgCCM*qQzxY!T15`WkFlweeXp@^k_lQdvPM@a40FLpA{VevugY zEhxK1{LP?c)i|Sww&ZsLee?b`U}f zs^V%AdQCQkKX$J#ogH^?I^8>gtt}H(n2^9{A$Ll*%W~2s&rC*wl1}W=+q1JCoOT17@06GIs8%;REhvU>I zFw>Sp51fM@r}qZ@)COR$HLz`?F_eEnJ4Ogbz0Ynu0=)s~!^VBF9dLh+hSvEgPW|iw z7ir_ge1f*}95&tlyl&WRRlh#`6?2`{O2QlCzY|=ajY#T+W@qthI^~nOnl^Mn59$3W zqtR-lKo@kVfOqI#K?3X&d8EJ+=8+}00&AW>i5CHZB@qK{z7DWRifPUB3SE`vX6uFV zu7^B4UC4$`DCs3W3d{hZtpCFT;R&C@y0CH>v3za$%OEB6FEB3(Y^co;t{uEU#M2hLj$nz z+hP5&PrvWB1(yeXcyoJwe8%3JRsb};d=KN9D^%IzpJ^L(l z{Cdd;wG&sV1+K(v?2Df9&wyW*6^}^JCbq^-&Z%a&AaJR7Di9Q{IxHYYK&b+lVC1c* ztRS*LKrE?qxKJpqlI$S4+^M~+Kl?Uup&(nooI&uFQsXTkC_$Jw*#0wliVDyguOVth z-Fi_wh0tX=0YU^7t}Z3m#yrd3Qvo(h6pd5yov-?frbczoFBD?O%KDeqHSu(D)o)>HV-T-RSN4(EiFq z|ME-b8=7Ca(d*f6<~yQ+Kmlx?{j+1{e3M!8zMr#O%UF29FV<T+2&hI=WFQx2O76 zezT^67{9ZtM||8)2-4;8xxf;`TpI|@Kd|zu6(*yu7taN zvFDS%yr*q|9^Jmdt*&e3$q8Q-{~WL7D%y<6Z96+;-Ip6nR*m8L>=@u)+L7C-l7WbO zuGpSiw9}&)MWHhKFz>e6?QI)0ZpLsHVH`5^DC+HxtX|&WG2i2WzSkhr9BoRXfvpX6N|i`ho3K z`*oD;Q1p4(R0B#5xB}qj9_4VkmW)i3Iwtcr3i@_KbkD<9Pe`H5Zdd%JQjESAAF7K_ zzd2;7L9gxHeA0=1lv5j)a@ZEptMn|A$h&xd;;4uevxuWk1cq$9IJ2&jQ(2~*gWeN> zS_)nqduqPm(dWy$>3Dp4!wiG3>Te}K^obHs2xwGxRcDGtg$DTR%?)&34W-c*Du^?# zm-rfx)nLeDr8#Hga*|5; znOm$v15m`lOpQNa;*8+-FMJ}-KSU3w-?a2`jsKR#KcnoDc3aekAxk}kTBR48ots!t z64wL`(VwcVZi#V-XI`K*;!eyWS^j`M9~Anj_mdE#GA+4YwcdhHGe_H+$IOBw$7)}| zqg?e3tN=Qh5Oy13Y$ItC8QxJ63vA|DCQDpb7sJfp(t4lKiw#<@fLQMg8vCoBMW6&= z1AsL_Yk5$jSRnURLXAlCbci{sREzTWlzVNr_Z|$rU*eABf7N$!HZ~J~$kC(rBTmO@ z0%b0>1NIMXu#kQF=Y&SSQOw^v+pjzb4e~SwSbVn4n#l**yE%n9&X+B{8$#I_W zPX}DtV(^uTb;;GD1$ zA3y)%N5;bpP2N66&_raPTx!nSjV9vkAq6lHFO^TCZh#7*5Xf^M7prc$WVv(T*NRd- zC+yEUAiO|5H`t{KFt-QY4gHu#aH&!p9p+9CB!u`AC`1C8Sp-rcOD!vV84pq@{#6J` zXJDy)XMtC)_n1tKwqWcz@h6G66>5Ni)Kr>}$9MF%hU46E(~@vGY^h`Q zs&G7|k~3(2N6J*6zE`TZl!H=C{i}oKE&BnR*r}80^vflk!F481sJO+zQfL-IRSf!7 zIR}z!9-YAHo~*&-94TKPM`fgzvk1U(361+-{LCo9EZPvaLbUzC0caka#{y-1g!xF5 z=;7$y2m`m=JF0czpzTqFc&7F>rS$&( zwy3(RDzEz9OAaRt?j@BAuHa;FTc}*t+mMvay~DzG&8%C0ArsYQ^3uYVXc_=?Fq{W- zp${2GRoXO2!%6h1Hlm0qvjjnU#R2aSukGa zHNQt&(F{r)JQFSn=n;!Q_IuZX1{O++G>t5O_0iy|U}{_BKYWSeIh2~PvK@sKg(<)7 zbrk3;ePJeFso<@)IM%Xg_#`-Bo@a^%oWTLa!vZX@no{fHu zwyQWKoCbd!KWE$BBw|4Pn|!$DedR~N%`^*4h?J7AguH`I zv`kFq(eI9w0gknJDvq$?XDrnzdo!lp z@uzg9f__yv7!H8;vdP-*Vj$ujnPGS}O&fE)(MMjyquT<^47dW(gh&&m%lDG33USTH zOE+}x$mH<>cXAvXRbcp@T2LTd7DC#2Tp1&Zp8>J`@3_Rl`Hh->ASZ3yWz)jHzZ-5a zf4)l@NiE6+v(;Pm*25gm)<2^Rams8PUnIOi7UTNA0;-N}nt>I4?+N0T33N$i5FY_9Le4HM%l~TD! zM{bWDGR*bc%2Bub;)lgHbq_&t2 zTl?RX1la{1ex=Fg;<+`uxze@yrXsZr4x_$!=u!xP-7K(C1gL4uBa#h-#BuQuG~166 zqH1iQQshB|524gW{%zK=$rUjGGRahWkAOmGT%l|leo1uglx&8VwD*D6c#vDTf6z&{ zp6<4cm~UkQ3#f7(l> zaCSRD`P^t?7>!LcSj|OG;6RTl{#;s08B-FJTrVSx#L`2cZ8i^zzg*4hS9e@G4 zGHrUWBJ&~hMC8;qL403aDbY%BN)0`X<|L9r4ohHF7->0(%k4%>lZ%4c$l*RfEd?A} z$dqk`-zOtR?%Cb`JzMeGt!Oq#m&!Qsop=$}Q+q`wt?ibV>N&y^jHYyVI0$KXm#JX9 zO%haC&@b6u22@QwX7;1c^5{xZrr*ZsVj%HT`--P6r7*r!&}-IP-gOGfdT`yV96?RQ z(HA2wRNSdK{@XdmWr50E{%0fzbV7WJ>axatu?Ya0awXRKAEjda52b-9(t&qDQ(m=o*^#3Wp zp=br{flvbhvH$np*Sim*A(c9p1dY~8OADGn4#bcsfItqy%*K*Rr~ruy_^T}uYuxV8 zGgC{x(}5rp-|v$}so&r<;YSBv)g!?Rd)YDv4vy?e{OJqvLV%C|=I9A~DqmJ1ZHoje z>RliAaRku)X$|oneYp8odgJ?2vOCOV*H@PM<7&w6qkD~XcgS!!)2mv7CH8%In8dfs z%EV`1fd}M$_^T0^KLxPS3q#wKceBvl+sG7+Dy!_${8YYj4sWFhr z^u~(9o2}mN8J)wfNF&u3p06Pmy6lgpL=aQ`v=hJ%U1~^GD&9No%M-OOWAWxVwUcF+ z0l}0%&Ydp_YJ!w0IO*p5)x^|HCbqFEX?f(nK4Cb&b+llS^iQt3s>$A(6pt_7&~%y> z(g34i2Kx5ItL7m9Ri5xr88Xpcq#jewUvY{fHe1V_qIt1)P2jZ{U7@e%;_+j)bM1UIY zFq-B8AfRdg%uQPfGZCWZgoja}9quAa3hkC)z*F6PmMs{-mJz9y-LoOqXZLrVQg>Z9Av9`L~6sASyy@t?%7S24{4||De|{X5y5@>?)2v+K6+o#UA_90 z)A}ieG0S4bW>nOMf+&4)_DS7}#sp01=eVaS8KR;rM-^4Mq&OzrDbyvU<79|)@rVTLfRr{W>*VS*MvGDghd{}N{UUOCtB&r-jYb4bHusbo%Qcg z<~O{QdS(VHN?a)kDS=Oeq1S>({FPEX3prB2M#U}Hfu^5+4*NnB_Deq&k9B}zFr9+9 z&YLpgA4lvR=Ztcm7pBydpDMIZJPj*!a|O4OD)pxjiklZJ;6e8>W;38gqmpWgB*YhN`)Z$pUAXkh-IF2e!RpxLJLdJ=#WP;#|+vjoCsy!i<)E zm$luJ+y#3&pJYmn6lm$JJy5d&+X5W{Ek+S}(j;hfJAZ|5`t{YD>NY)R3X)%%)qWAb zAYxCbeSyZKZwhe)xl_crus)o7WXI%SG7wUwTNm?#wJ;d-0T~0R?{(j06Ogf-Sqmq#oP?Jo(|59F+E1X#dG48Jd5bti1pdg1 zQGXJDPU;&`W0vTN(-Urv;SJ4Cq8n0HjQy6jF=#ry4j?Ne!=SI;lcOtF+EBBIo3_De zA6)J%5?y44YNGH>)kK^iiIX^6;Z%t#hY(=`-P9=5{!otsxb7%Sf^kl*js=1r0T~8< z{PWL0fBEZDH3;FEa6`ZEmpV&;VisiIWq+-+5TP@zY~RKH(|Q_I+o*yDib|I$E)}S@ z1tNRe<#ruE8if;%ox7-k*Cd`R@8mE5F=6*Cyz`BU(Fq*?e5X#-v60N`198>Bn?3>3 z)|&n^> z8fP&vKtI`y1RRdWTDd^WGroI#`Q8_B`D!y9%-!wk^NqZrAVFU3B7mY5-aA5%Zo7MkpT&)n6@7q_kqBl=x}_<<_E~h>mFxUSf*tu9*dR{R-i&inU6<(VvY3v5uz#ABU(%*f z8r^Z1f%uKQktFY@v0yFG#kZb@7z;BRTwanaq-4$>MhajK{RIl`tsBgprTPB&ZAH}a zznQs{))&2P-8M*L-M5)L^tc($*b%oecakFt;Rk-i5EC!fgL0#uOS=%dN;eUtO5E0H zw$6>YCq^^3mC$3NMU+T$bbl|Q2%&hBiP*SQh};%$il(=l^H0ogab$V$i@}du z4H=TtICvNLu1<iwB<|3c?L34S07I=g_tMtj!d-w03|N8aI=f7VA9)DfW@85qwkK%%{ zmL5ICq4UT0AB2AQ&l^y|nKh>Gcnwq-i)zsIJujdNlr|0HLf7a8Exa>_i3CL!bCiX0 zBls}c#)$(C%*mn8eF+Hw{=0W_35tJTT6b_v1*NF%f1w{&Cekr0C#8Zn4P& zxP|~`#v|5wNV9W>C3FT1{24lciVnbE^w;bKe@*e|($LlJ{535YdZ#0SJre8}yRw1$ ziVdvd|BW_KqMTUtkUDZNX~7_A&fC7{RtqYGOxB7ydru}3Xn!`jI!v@F_d(@i(IXo+ zDylk2&cH--Ds6V!S(J}gt5>!3}GzFu^p~A8bw=RDm)aOic%c?R6)y#!Tp@K)N!wN?^eQKatHd)*D`G1}AY2KI>*a)D_@WTpmby|?z za)~P7jJi}}#T|N37QL>+;DF~xk28e~QWo7p%UfT-k)TMWNwot&jbQq=g!oHtoT`b& z*@eOF&<7cFv$|GHkXmhvg!87(WJOqJS{eO9AEqiaC3Ua!SKBS5VFsPSVUidVd7`2&7or2k#4h{ZF6k3+GZMp%B{zP71yx{GnK-= zk|CwTCNdSN_)Wu6JJATO3#C4Hw~Sgl1Utsi-E<^J6MZh#SC7 zu1Tm?XH0CT(Q@Uc#Bafu(Yk^bFNULAZ5Xtwpf)PdYa5A5Vw9wZYu0eGmC_>+hnDQQ zZYa;dg|wR4`5lTr-ZNWhA8dQdZ1+(Cc^Zt_E z)PHMC7w>$%SVuro5u8#sb}>?hJz`vkuH{l%S!xDDzuQ=cMR4_7Q--y6gycIFwPgvP zP((hZ@mFL=30`jK`TrO5D+kQsVd@yXNnQI8%2Fe5pR2N!62AjK3RkE3rZDPy(oX{u z+>JA-qLXSODC(^$;S6yph+YZv>J`JV7L0*RUNlpYR_x!y|=a2K{SF|F!6rl!DowaWuF!7k7#J*+|{@x_?mE zC5>fV*wfig0vqA(vKM`?`+6elV%6(7k=S2CaOg#NJ4(`%>JdFpR8`dlxxb21q-QF| zU-}~TZbB*sx~MaiLk~!d(-)noJC{$#3WPJAnZ8}b>hfsctT$Z@dD0bMO<14^8a>iV z^=4WjjWkz(;jMi88wJx9gnF=nj(=SkRWKb+-XJSPA?ck*KM$eLRU>%ExHBD=qA>=e zej8OJtYpe|(_PFqh7_=azUMyM=oM4CCvTT)Mq3AHxWtW>MXzmgppEY-> zS21_#zcVyD8Zu>uAW8mYWyn-kL#6E!Tqq;I5nSLY7pO}+hF?Ib+K=3}U4K-5samSs z$IE!)dhxLewFIv3w--Z&9t(%Q*V;x29a66TFp)?F0l(iQ**Q~aNqg#+EEO?1-1W#c zO-j{zcQ?E7vhj*XJX39o%gGp^NtOPl1HCd+!?|Y|2M-{ZJ;~QF4%%`j^pjf}kdg6o z4xeEuAFG0oJG!)F%Eaq7!+*xKFzJ%rQAx%jcQ<+_tORm1MI+m(DM;so}m{WS5I1LaJ z^iL2Mi*NZb*(E%#gKMYENZdSP3qc`UJ52`zz2o(a@aHZirkw^EDu9-N!KXK#=;Ge} z;itd<`O8mV|Le;d8-FT`rd1y3q9OCNxN;*yUcFH#b!P)iRpS)4(Wg05Tv6YM5~@!@ zseCbcOsmmpIAvWI)b?~|>P6!2*)_UvedWZ#FDarRH1q8SO$B)5kq#y4)nYeXEtXu} zTDDBK3pCAA<{OsnaTwWMv+3_kTjC?9|5g_b(-mgBFa`9nwts3)VvlzB+zyUJk>A$t z@*$v0?uI6wgn``>)*8u#>pHUAx{C*;Y+lnAs_*I5?cxYJg2gkNMC9z=%j+BfqoeAVSH6L&HSIiPaa zJ?Z4GKk4LDeSgwvd`2z5e>2en!b5!iq(pH{D`siWmsLorNBFsl#R-G3x?RX^=yUT9 zWp&3d$g@EGZ@IquYGi_XMQf%VB-KFBJ;eZUYia13z#UG0RYeIz^1gnfqSE_`&VcrG z#3o#aCen1|UP5)~xhbtiHg)fam6sIiGly>@T2C6UVSn+4;aj~?g6ljbOC~RB>UrH`>^;W}V7ovjU(ws(w-}U?b+6NAA$3oBhgI+i* z??yui-uHSR6Z1wNu=}~ab z=_mNWxdi%(fBsYQ=@EgxME?bkUm`sH?c<*ap_L!9QsV;j z+ch{Mu+#;pY~zoY53;eQKe&cW_I6;r6m9OcS4z@FEPTJ#v}A1FK1cf60~V=6k~NwFaDJ?`;*@qE^^rDj>4ClA{R$6~sW$qX zQ5DLGQ(6SQjfYG+7L*4zlz{}#T>1b(OH`{R(Q>pnvK*-`(_$wPe9OE z6Nvrr1RjaF9BKmsb5N|1lu?OH_a*(8m=kR(fBs%5J+X1xRU-7epED6LF;Tux%z|ir znQ=j5dVf&37{D9D2;VI76||=khP=3LJ|+HL>^U97+jR6Uo1vIu(wSnvhk;5h%L;#Z zc%Nd_vp?IA!;)(ztXkl3&0UXR=iJ0|8-A&)1$-$_cEJdFj`=Zk#=jZ9j2~@`K3V98|99Of>NRDS*R(6|6*W@fRlc*zGcQ}XqsYNftk3+6xkd1->LdgfKe=KuR^wLt; z>UVvEtEG4YCRC;TtzRcFXENWR@Oj>L!^0la`rxl4ePNA_U z-eW1{X%3r##fgzyhMQVcf5X^D!A6nx*GLv4DH45JsTOn`Nl}{6!fQafPF#`rM~+Gn?1FDPhOo69wgPbI5z+X@3^q6xN)MwMa??WHf8Y|)X{JH$u#R1# zaT-3|wRGDRtwGPWk-+iP(}QC`biYVi(2 zzdQwJm(S)=d(w;^R>%T<%H8fZ5uu+K$BLDlxNvP5ZM|diP=?Yuwt1F#Z8;QS3xKH~r(xp~e@Sv|%v7v{syA9NFsT`L zt^v9s2G9zMZl=dMxhpitGu`E_}*nlUv%JVVJHFwcPH2%KC3h!m?boppd#+mRcJY zH$b2HN7;)*XJXZZlcLUn&4cg6v ze)Fev$vn=9DbIA)+$ay^meds9ED!|8gmE_t1d#;7e`PO_jR(41gy!4!r|#M`uksNW zUmD&e9;?*$ts|)}aM_XhjK@mdn`l^58QeiGEqyMjiiK~}7b%CXuIr0`7WE~3{FHO> z;GnAeZ*0>4x<4nwkImzqU|O!4veNjV#O0X+2H32^ zp?~%g)j!lDap&6EqT^=?R9IZQVGY%6M1gH|e>cL^N)^^Lx?9!+H4MMcbvG`{KqqJh zg9nc~8k&BpriAiN2=NLmn}3rM6n-aXawJF!4T5Ur+!E{9zx8E<7ps!A&^d}JTFu3n ziq$Q&z@Q`dcg<#%!G;3E#%*9d2^Fh|G-hY}tJvCC#9#Vvw{?xMF;9*8`Y_BX>EaT% ze+EkC^-Fz!b(VMqDhvL$uEXOoD#54%YQ!{mAX1ZXef?5H-QYkZDF>q5VV(5AETwIH zr&6)o5b9PL&!olB-a7Ikus^C?>k z_1Z2e58sY%SGJ1qc(l@I>8KAHSrM?VdmH+)R>Wmql{SDfmf^OWlhRUm8BW%vUfv~- zTPpp1EAH4)+dj*~tOb<~w|(^#vfBog#{FBAoT0`W`nMg#R?GitgCq#Pu@3^$*weR zuX$ZXX!>;2M2f%oCXz`_q=;eVzACO9j&V!q%Cy=LgdY+kCZM3a+Nc#x*;SNV%WK7w z+i}KJO`MMhS*Eyd$eYPfIi{8Ae@}E2{p#}eXdbMMO~p-Ks(G`^C>C|oWpz#seGFW; zfSU(2yjCj-zri$Fhw0D@0Q6n};4NMNV9^Ws)Xm6-wwVeUMfsNNkF)awiSRSh|$nl7Qv=m{n16dj|e^AK%m|rJ@ zu6WMw3oK`GJ3NzX@bG-EXY{HOe;6`pVUMXi!DlJJ@SQG9jUY(7sBM&LbI+bHoK1gQ5kYUu zgTf}wL!`Lv^3$-4w${9^aw$5lIMdG6cL2xwS-XQp0r|%_hz*K~d<508emJh9YOUx7 zkjz+n`h@p=dBUrz;=WA0z?R0Wz2F6|DFDJ7Uhp=MYcF^kkUxL^fBEa{=U>)d@HUXk zFL)cMXWyH;|L$SrqWr{b$d78kH5bLnD6PJcP~etv-P1W9;a1E#xx*voZVD*Xp&Fou ztnYtKX-34kzJ=GuX+RLROSaY5#&HO7>9uj1VC-KTo0HeZap&f))#T<%zW&FC;tW$e zs|Yh5gcD9uVQlKhf2VJMbC5=+_Q~22-TQgwvTf_*-u`rMoQ4RasT93sT(5_CIlEvz z9%GbelT{{lAf;%shG_QMil_2uZJwz?XAi(Bo7GTY7TerE3X%DROq zjz+^GoY=@4AAjVD6bJHOjhH5{IE!R``&OPk(HVvXqy$Eae`bfp7-Y!wXwwFA5`zq> zuIi92%wT#KttkO$;1=G@P+G@L3pJU+r1V&6xkDr#9>JJ0VS0kkPeTB7r<**mvCJCi z<##-kS$gfRnjyH3hXzTbxWQu(6IUcP)56?P5p@tlR|LE_Uf^?A&kK}HA6(WA4%DjY zkqcd$uKkvm@X9}qgogUrOL*<5RM;K(1|JH3L|ls&>5>nn^D;xlZUZ@aBZE2&aWo(+ z&%Cu^R&}Tr-dYIqY37)pXOB8uc)i{uTJoX(irC3ce}2!ChZ&T=cOw5^`cQvC4-Rip zDM>1Yz0sN3P7i|*q(N+3`zL5Y0MJmOPK^g>vlcj)%G5RJqizAJ?18%?xy}U%thy zm2X=zCA*aiKB{Zg0DSoP?!O((-@XcEZe(+Ga%Ev{3T19&Z(?c+IW&_&4=4mQG%_@k zp&1l^y&TDoWI6FZUs1>ILmNB1qokzH$u1?3+`*{QX6~{Qd{oKJTA@_|2P9FG`7Mt@1CQ|Mr7QZ{&-5306oQU%a;hw0Zgb z_2o}DDcwgYZIJ2B>jx#JOpo-Z^hmvGmHzjC@cKb}+n=ThG5w`a{f6IhgnOhvNN*s2 z_NQralb@u;)sN}_d;6aM9Y%4cxr2R8NX95}{LeQP%V&Sh3I+SBSDqw{GjUYbM!|D*rW;nJZzn~OB$8n(R zle{*B+rY7Ljm?Z(v6+fa$n=PU`R@LI{)jU{8lgbVC(BHb$dO^bUxBI}E7PhRzoDXw zReh`5#BtJnoMjSr%r*-%LXa{lQL-Tscc+rw*4>fDy%mbKFm0zh5||OGGIB60M%D@Q zCK(Kh`FEeceEaF^mtX(={zz&JcmZiqHuJadk2W(}3Tc5)d3^cxpTB(j^%vYsFK2os zLYy}Hv$XOU#ANEc<80LhduOA6phWK5dfZjoZMbJMbNjLRI8xo+Z`Hu6|~b-_V>(M@Qq|5vk9XEfumM=h!@X$2s>188Q$$5c-IAhY2@_h=*b9A@ z%*jSBWkyCJRTnbGveI5x*k12`{^i>-*_87MAC}KL)lw?!wrSEa+bbW1 zOJ2vk&oR|haKg>lEBKIqO*ItkAwHq`SMD*?N}+5Sg=9*WhZt3E{Hg*n#T!D0(>5iA zZgw|WFx=F-OEzxBrEFY+?s4~Gn&HpJ9&XKDF1{Djq7_tpB8*dUZuD@GkiKqt5{eaB66X(~6nF>oOWE+)_%bZgUGJMeISkw6(`P&}pLyRi8z z=BQ6#@-pP`y3i*9uL#*P3|+8iiNq*zfZKe+J(+|gUD{c8?2DQ^5dvi3Gfy;kj-dUt z+2pFMsjpMCYGFg2P5dPpZsVZNiJ3GqE1BsqCk&~A@M*OPB*Q4s<>ScN4hXcOEZpYP zDB+bU^QLWQ{!O2MN_y%o)i5Qoeu<<#)Maq#a3kiVj6egERLyFG#4*bEREJS5+9^{J z#rfA{gC&9fd17AqOCW>$=sx4YKv1 zILxGG(zRpwbuyA!RLJ_*l#EKgUUrJu%wr{!yh#Ce+U$~&f$V`PH=_Y*hEcrk7In)> z-FgyH8eGwn4#;FJe!)Z|0+KWeDD&c^5i$9ZNDk-tO6% z0x*!k*?Ss)ql6J+ql|Z-qwI?~^bLmw<|u|>u7F|g8|_Eds@8nuYl_4^sP~Jbv(CWd zn0sG?dNbuL4#=L!=oM$5Dg-6_Hwg<+7s zh5*k}du`=yLa$OolRU9KXh;1ZU7Y0R-r`s)*+XjT(d+!~2Wfw(gK-2+;(@lavt7nK z=R#|LPt1A)W3wb8#$Q5=y`jL4*a0*Bx}%PU{CoQz)+*Q>REfk+&$KqlWpv%4yDw5- z#b)Hlvu37&agj;vDbo-#j}7L0O!4>(akEXBZID5KX2Wq<4(ncHdj|K8z+snGMAbTlXWe(a zWU?&Q;!3n&<<`qAFjvw;{u zYe*irjXU(7Ok`E3JV|XTO=X?aN>dq?xv+B4lD?4KTodOcHxIlH%gZ(J;`LFb?#$|c zuu3HL1?9x|bvr-BStKN1MM?eaa>yT#T6WEo)ItxP1;8T}R-+Dj)}TQ@A#5#|L!3aU zsj&+ZRp)k77-%rO=P*Msw;^wBj-*y$IJ5OFvll@Vr?-egGrfB{v7QD;)0qy2h042@ z%vRiD(=5WD3P)C~p4J@QikK!Up`GG?8Slg+&OM`fot?$cd2%r1HL8~CJa=0&PJOcx zEH@kEvBIf>b=0$|-!{h1u|nu-#!hikcj!0x^22!4ig&Q2rc!0yc%&i8^~Mp z2YX$0F4E}XVD=m@qh}Is=&2xjIXrMCb&ZreeP87*hISZ0=(j_?2Ua*qT2BVRWedj+ zaM|g8!tXt)5a<|%i+-;{;O?XU)V)SWymt(hN6(p_d<9lWAihF-j#J=mP^C5%E>yd& zTr-LjO}AVqO6ZWhLpi*E!~4KdQAHRjnq|0ZHnr>W1U|AT4hz@#x@sq0cI&Bc&3azV zm7Z5^iul{QaqeX`S;4rzAIeAlM!D8V!nN2!z`d1;kY*z}X2kUygwgB}S+Pj8=@JKc z1}-xUrNi}JNK(=cLL1@@lAyRnNxkLDOsTq&MZl=X&~B?p3WTJ8rJ;8S2YueGfKlGW z%NWIwOx>gJzlnhcZMTu1d5VfHfl^%bv{N}WBggjG!S1QwVSwT zX5A;;w9%YfL;O;I`)lETgM9?>7?_XqE~CWCrAx{iD~xvA9?OA8V+%9hISeJpu|Rel zNf(@hm>u8tOnx0f1+*I;;;YsDSWwkhzTyBkcs;kCSSYA#@zpVRsA($?yt4e6VUT6j z*H)4&mT6CWU~0|sEYC#wD|%`zO!zKI9z7l-7UX4(kxU$aZ7Aol-`r?G3Yn`sY(Oti zQ+*$n`hG7s)XEBL!m@s@VCBIpVAUzw2(QlERi#+VJLQD>ZNH8{$8!jmb?mwttz#>7 zHD}dV9dK>Dtn#!M1uCY_s+{A{^|k;!TcK8{{=4YL38^azOD$|1z2T1$dhkm*^ED$w zHFvZJg^oIZw%0GCo$6?FkXu*W*uQA5xGielzkj$(n*?L-jX)9+Of2W;-)}@Vc z#2kEH&MQt?!jm`~tQOwGZk+wG$Jth{%St{BNU75g32Lh(tu^*=h;}*XUfAhjT_BAi z^||NvFO}mjHkpF9l*+*aUuYZOmg*0GoDicpCS?@7q6$R0_2k2S>Xl-58qt3=G{k~v#H?q0RyRj1Lv&9`Qbcr@a0gMESiTMK*Mq5J&SCKtVZ;3bpz_I++3m5j z$Njum7nPJH?dJM{J^dk=GG{5Fb|eXS&r5~R%_M!`exrla?IdaI+8b4A-L|KHaeXA- zRXL9v4W+hsc$WHPGc-N#^=S7ttfghQy4L@uv7Hvq*h?C_gu44mx4iDB8c%>{8%ka< zxUGJ{4d~78;GT67#>z~-8XHDdo)2!BwI}!7*pbIK9+R@}v@rL}^7;Uf2y#}&tak$oPyf+w#@oa6}*$L_;HbqL;F`dYLjN)W@tAA&+luO|qq<guEM7Yw)#rJmFW*D-~rH=l@&|(-H$7hpsTXgh_!)qD)*pr|5s&n6t zJHSGUMx~w(vo4EyFHG!zZje{CvK+7zuJ;u&sfd2nbP_#vST<~z-X+cK>J6|kxm%I? z2YPDN@9HwL{^{6n@35@MgWOr(kuIr(H`CFd*RO{((9V{G9N%QRbh!&)B2LV|oWmw3 zskiF3-x*W6!F)KiY5s!(dHGH1dNrdVlcvGiVtG57*U1 zltRO_DEFoQ|F}y!Vs#xEA_$j4a&RI@ORpn4!zO(C{KJ0%NIW)!3T19&b98cLVQmU! zZe(v_Y6>|vF(5FPL>UDo1T`@@IFq3n6@OgIuH?84-S=124~!#;dKoA*(A6~+AiE&5 z3$jX(Y%+_i^81lQks@W;w{CY9g?nx5O^T00O6K;jo4Nh*i|KzKzkT_`%ZA&&?a@Vl z`|Y1!Z24er_LjqDV85jlHV5U)@3+6+jd9KxC_ncw#(p;@KFhDY`}&KExs-rkjeiNY zyxq&M{Dl`iQwi7Jl&4nQ)duL3f6j&L_vA;Xt;1b**q&bVn`m%=z7Mee-|Cld-eE8J zjr(@8-`FP_dY|?GTE4b{V=n(c>m;li1NIEM)oFh631~rI_3d6~ocbCVF8Anf)CjpP zT2sB0IKi)f`|VE$l1A8E+KHrc{eQqGF|N{=tIx@Ob<|{?osYF->~-rHuwEx@uY>LQ zjP=_3zhph#XPtHI<$b2N!PlC-#dy|QeFLdJF~^v%gS$+v%VPv;g;wr?&HGX=l#YE4 zwMkmf&Pv{K!=Zj}td)-gNdMQ#CBZgf?n_KU+*OtZ#K_rRI0pS$!)QbFf1|=3J2%_6;I$ z<~mJpy&`F!-V?{!CeQ^amVe|0d444JYK;@?7qMcm0Fjv3Lw>x_CA85GVPnRjA9m|&$>0H`Mi%hz%p=SP6 z%rB`2#&<>41sd(7@&>4pyX{gHOaNT+VO@B;(r?juN{fqHBpu-G4_nX>G$gwu`*4 zxiNkfy3htp#CS=)h0%lh&`wa^$5_9gY53!nda~=iY#O z4FiDIs4=!76QKUTq-%mL7U4vMb;1-EL`64=)Cw74QpGeoFoGa1NQ)N+X|YrtJhtc` zV!*vWVxY*5pMSq=*Kjyq^-KCy$S5WBv35APpZ;CjmghuF2rsHX+evCma4*_T^pkzi zxTne=XBSchN8Y%rlaeGdaZsPhscMVSZZR(OQn6<3eOQ}b&4a&ohQp_GoolRp2*+GW zIfoMXO)2M;oOeS%JOu}}GKbB`K0^OV^nkjJJScm*Eq^;+5RH&PjVUuOk9&>x@KA%y zyy<$Zy zF_pKYN1}-%(Wv?nZ``o01(EA#>C;>dQz2Jm*B)IL+a{)Jlt1~;2EM9UD(ndq$e4?UUE{Zxb^Ey<$tcir3FU%S8RdJ-@pn~PP;_UrV?Mxt& zoO8EjR|L1kKZJcYoX;!d3Ix(0&}q{G7Gjnj;!YGF~-08-@`dcxN| zQGfg?hpExr#(AK9k?{p7z(bv_eV-;%gg`0M${Z!g0}&lqHV6TrXRdK?T58fPV}>iE zSLpZ^WsTi(_U}>lOk;-(+a8>Dl*xIo#7{!PlK3JI4g#)jU&kUV<6W2vdC-Kxj4lI4 z`*DFZQ@fqr!hziaX;069;CZ<#JEs?6-GAMhNCN+)L8m;VaP`51UHRZx|05q9ON}~- znO7?FrvPu((2tLKi{8yNEIX%dS&%m6(dN2>g@Q?&k7;iCgoTpb_MI(!T9YQA(*BbS z;!+kH9ori#E5rUq?BO7eTit_DZ*P?_bJW5$*HB#!La6q~TH$C#0Dq5b zq3SSqH9o@N{RlTmc%rxY0YCOtO~VB6OMw%j*^IaAXrR9f*zZRq0S7}+qWinXgIBg2 zcz7!~1`7gX4_e#!yZlBrOLB5NLzfI`uMiLY|2!0{SJ%3thJBFWH zcxwt>DWR5SA7^-_7`+%VFOo1DXC_w0=A=jZDji5-??+145`d#wQQ7&;Cf?p8c37H; zuyAuKDG*gufc0B3*WDru$nSP@BUA~6lS><>2eQfEBnM-jq(rqK1&P}ym2Ba<{cP_# zBHbwkR+z04cEe_7Hxb{qb$@LCiJ1G9nM6~L`vw^p;-pZE$*YjJ$#cYW$}_4?mv>o( zps1b`^KW&D<>ZdTqIEXj>~frI+~0wNek#>_7Fq7iXC?(H%Xj-&i` z%q>t(2e(!8A6gqH0iQm<2WDA}(RDSo*an2Pmg^ z?w#ScQt=z+a=7mmA9QmFvAwCD8d*I}!LU%J5q*ri=snkKW#t_Uz=TRn8|cbQf!%Mp z_!83^D{?C@rSuUnA7=pexUF@TmJdxWe;*1mIfW>_vvqygeB!N3nKiigk$(`DnE2;3 z8V|){a`w=!CznjPW`735Vsj z7HpPCcnfbwGv#RcXoY~MfKHQMkv3NwRvZ=}wnBCYKC$+aK!1?1Hq^F__JWQ{DD{J) z*h}d8a%uX|r&~7>BP2Tf{av73hJwx3?@>gsw%FS!MA={LJKXb_>x- za*@^V-Tq#Xp(Y!diFNVK?5U0D7?*hIJS*&!aep?TndU%IM{-338Z`Nk>?IgxSen%7 zH0PvdiIZU8pMTufxZ4th3G(R^5y^TobSQJiJe$X5Bdthi_AQz;!wqamIk+^WY6&lF zVp=igMz;zWV5{e5)~qh2-#*JsT}ru@YA6qFSjR@zj03^l31(ggk@YQd<%jHr#MPOX>jG@VdXf&n^z#YnMn@P zWwawaCVwym>tuA?g2du2sHrSvqDmXJAQFfuvc+J7J)}C?Lrfn-z()JE3R+vmCE?vj z`IwaC5ie9!rc_`%nF1@KC)ko7p$6gPXsm*>I(0VZlt+EQGP6qd9dLu)_7H4ZSnyEn zUJ>7f1_73zQ@8^eXB|b@`9EPIJN|ANeW-5h%744+Fu_QuMkJyTzx^%SPd#gSN!5qz zf~CsRGoG;!+i$otQ1iq+tU@se2Y*&m0On|3_=BLbI3-yHSFt=DaRm9b*K)`_ z_V8n#i9dKIZ|0--ndo@MnD-BBQj85WrT$IjL$5YtP1?@GqdrfSzUs4bBYY<728)w{ zE`J(eXm{d}&2A7xp&i+1*Pb8ROz2`Vl)mxfvJ0~*%u$3lM@VyiZF25@lTpBTXC4}0JrGM<6 zD0K!p@>6yYX_XY06i&sHbxxk{p;eKIb`Yd7DOD%ti5#?EI2!e1Qyv{Cu0d-U{0|&~ z##)N<;lq%(n1DEhM#qclP6=k20~_SYEyCgnb^%8zY7$(*;mk=I*wS?TP34iZ$EtcdXdSS||$F|=Qr&zZw??Y#>Dhmu}Q&nP( z;?y?yt>Oa{muKkc{7K`?H0H;tA0|xVn`R)x$XrONH6s#V-K307oDPGmQ(|2RTe42l zaiv$sIZw>zjZ<ksptiU1^nX-q5LUt{ z`-5hpJRDnt3#j36BK22aX<;EU-NCTBBbnVLE zlTeAx2x*NaneZYy6Cx*Dk>}5cy&k8e1iNL!Tp*W&7Ji8&2eZP8!+h)p%dPTNu-Nu8xoNqu7t((Ylv5sX3_I$2jIkb5-enqEWIQ4~X9R4!X)fcgAk}NEqVm znV>ITIAR1*98$omSbq+8AgFs9!ViT?x@{{rU^6c*ZWQQIp(x4@IKdw>kVGJ7*wHdZ z9F&z2!u>pNu+JzjqJg7rnWQHdkxOwXDXfmA;M=3ZUs2NLqJG0ZfC`=BM_@@yMNrZJ zg1ZkJj&hS(*~YmH@~12z*>meF(xtqWx+}d%d@N51c~Ez|0A0_^fz}dlkBaY4c%0Xd6c`a zm9~!ig0_+ryAQ%&&i3(czJD-CZjFnZ==?ck&GmG+gQjQf#p0KVu8Zs!yqy^RUF)<_ zogQJFwfjs5e|Q~|5FXQKpnrNO%AADY(AlRIG~7`}4#jwVQ)jQVqb2W{2?Xm zgwO)-w9|%m$YQ4^=N7?vXNF^z^_B1>=187&0*>?j2~7s-1mrv=vV(K*p;Ez`i(xXJ940~9AG~sEQMW3n~dInWY*^Adt@{H1Yddn zAvvx)g@yCtbF{KktmJv*k$WsE=;Q1=X1PJ9I0QV~`?nCNczXWzk5Cp$8&FcHn8ms*HtPwDiK5*{=G*)Q`utOHiwp|ARph~S|%rBWV77tMoG>#*@roNYE&(- zxd>_eF%GL~s@p{h*_h)51Ied+OOT27mp-4>VYy>8 z0;=7IbUfPl%d}|H6HuQ+-SK7}DetsrN*_6NAs)_-tl6IpB19{)%`Dm`&*CP^8RjY@F}gf}ggnr(n2kg+f zNWKFUFMH;Q$D5&#kH99f3m*lo^;l*+kbPq$kId@?E2pxx&Sl@oP z_Xxxo3IIv|(40rUS;E#mU$4j86h7juLexRiDs{p>aI|j&Xj*3s%QFs9P|HZdRXezJ z_`}$sN*K1(_}AdJ#Ql;3Tn-L9PaxF^aP%J*g1Eei`;iZ;xw{AXN-;9wTDz<(lRxe$ZGZl-GC!9- z)_Ys5Q>wp5o-jt%9-@z`e^V<4n`hS`)j+L3aAV$5)j{F@J9;k~6gw9Gl60fgt3GrC zZ}A>xyT~08{;=Xuv?^?o<%d5}J&SA)KYS1GKkUi~6@SBIZTh1bDFuhat58$=mVR&! z+Y|_v(_qI+7uiNZ04u)$=|D^OjVhu0X)^inyI1i*Cl`5Kj#PJ>`d07ois>@@<}Blb ztl^g9>n1!1-(>5osLyUoY)OtZ+=fIlniSPbMD@H1m0BDQ!}IFV*lR92SKPc@RYM8E&hV`VOaKB1I05P@+q2 z#XnP)l9_8r+J!awJK--wXJeta7mN*HImQ3N{)$bVTRb8spr%kAN#$fWy(je1GyxxBwJV2uvKBNgbBmU3?_fNA9U8I6fm*4BMrxCb0@ zg)5_AGBjHf47zA<&sI&Gdr%L7ah61#Q=;$Sw%RqRDerk!VDqPkVkfnO4R3ZXS@O0D zTGCp=_1T=;1v&;ryHiTAA}XaPQJ3{rt42L8E4wUkL1u57yuUs-e_>I z0GqUtllBIIm~yk`n_Q^eeoZceCdq?la)bM8kSS_@EkD`b@hwrWlIV4|BE8SnqvhYd zZZxL8!)&s|Dm-{M5lVIaL{75wu_GC{Vq~V@`$qS*nl-6&u_y`p(i0Fr7SsqCwK8(?U{4JnR0)<*1K=bPBV#Ret!t1rjnX8DPWG~a2!L1J6; zrqzg@nnSaSLht)2jY3*VAHhFok8t&z0P1O1BPkl&jg>e{p3*@X3FRhjx=>Ih}MA6^IiL0yutl+i&;t%yEi1 z?}Z&HLCgg$Cz&M9rnh+u$eG70Kb0PpH}K+fx`|JLns-Vxm_qO0{?$*kZTj^RZJgLO zPU++(1M{0!zs}zm(LPOre|S~a-WlJGy5|@qs?O(7c8=HjyzxQAXNFtX{OuyR>rrn+ zbnEZgK^Uo{XoG&b1yD669I_*44D#2GDR1(bOxb3&K~7mCVq}q!r)!$7fnAs<4}st@ zIwp&@P}KI|#C2bVs$)$nnld&WMo*czsYi7KA%=YIMuQA0M-G*dhG;oGZpiu%bO*Ph z^RGg&PP3-$7k3$F&g((iiuYp1VWv`*o4wi!+}?^!dE64?Jphi*$7Ad)$}zD8KOF%H z1w+TY8&;{P`@+bRX7n)6%*iuy_0qdOQ^A)3N?xyT=XsL{+YlRpSF$e5>J_szVBH29 zg{+xjl+)7%Dz&U3mZ*Llel_i9g7(bc5kuda@mElMzc{`3o25ra6x+8X38Kp($TkBg z@Fcz`GaBw6tN@Cgw!+JgMYl1Tcx367h|>+u{5=a@}jc*_%6|B@gb;o__!jNeHT)DJ|G%5 zF!?G=a5Fj#x*9ZePG-i}XHHq36Pkn^1R)_4VKW)+zpnkkjUF7&rYg1ecf? zrAH9Uy2f9VffJRR< zFbS5bvxI~Wy@lh5Y_o*$CMq7wWUY3sCKQ{C{V*>h#!@?E#3q@Y$gxs8P!xf5gRl7M zoFP{CgE{kMmEH-=CT`i$*x&~zb8tiUKOh?ueb*Y}++MgQH68j`^3MXvBtnvy31Nfm zuU*bVz~r4ug@7cm`_96_nSf4)G@~uR{dy=&M;S%iWhL;i=)unEvwU54?;m?4kcpWN$VJ)3xl<0 zd}^+@FmLI^FS8fkQF#~ZoAUL^G9c0qZ(Q8n%0B-4N;&f?hA>Oh*Di*KcQ^{c^7$fL zPdbyon^U1K>sjUC$OAW(%QGGJPAEc5Koy>!2V=yvan)Lp3Y}?%ZMx;cX2pkgkhh|s z4zyg@mPk56Ftw3yJ);1wwhIyw3&~agVsF}UNY7lc`6I4FN4gUv^I2$45x}UR^t;w& zj>hQ1m-S~|`xbPS(HMe`=^+=#rY~@*30GZ2%BvvMlB)=cG_=Gdg@B-91><%9{esPR zGB?IasHL;;(v$QZhsmD!r(QJA3-%UYWy_{VvU!1}yD>p)sDGs(%spN;OB%fNB{Cjo z)s<|U3*T|9w5CVqRz|!)3Yd+-fTd3LF>5`=j@@IJLS!-L*Q-$Xrwh6^a}TZEXCOe{ zaZ;HFyxZ9#E{tc{!|;Wddah_5&+b~jqi^t)qSYqp`pT$(R6&0{4EX0>4K%4W2N>%F%d(HrU*WDWo#UpPOUmuUhR{GVpSuiHEw%N3pe0DVWQ8wIq$^w!OlBJF1x^mJ4mJcEu`Kjgo z#_}(x>0Vetcn{7DAeGQwv>6hZs&h0b-QKmKgGkEGIR>YF-VBxV-M#8rZK7He+OV3^ zoWZm$292pl8aZC!4M3$RRn-JX6_qDBV`J54kw;$|;;>Q#pwpo5Nu6#zuRSS!yjas@ zv5~~qC^D%sN@1v;x*2A+@jc%Ya~qbr0_Qkh0+lOH9;%iM%P-cs5`it7-0@5Q4!)uj ziS0o(MxNV;Z8(|RnRb_f;#TG&5qmT++qSN&635KYEwEc_%sTQevMP?jTBw{4JicCY zZ|a@S`-oQxsM(nd)VVFErAuUETkuq?W}@&d-u!q^8dW54&Z9>^K?n&p+lBtDUZ#&` zqbm&h+Z--7oF%;e=b`Ktr5MMg92Jzv8{4re;$+XsofVt&_vM{RjH%$ywJXEMb)}4e zb29n36NB-;;cm)T_av^a3p zfSBG6pz~GYtY3k&oTR27nBM})n_eC}DXZJ>D%+)?H;HOaZcoOunsu}vmtd(-GvZ7b z?cl%Wj^OrDOwF;KZo)2KfI`oxwG4@;~Z zDfBj)ox$`J%kRe@jKky#hc3wDUGjR znzX-11d@Zw{~+WiBsnwGys|r828+a1#C6lPjAWGC^=wmXJKFbzoETw7g(qt&M2_-5 z0f-0b#F@Fphe3+oWxCi(0td?D5-_!FUW+2?jgWf#Fmbh_Z=aMUyy+`EHkY^!GjFLD z5;^vS`h$F0DAH8-!CohYWeN;+hLJ}|84c#d|9;`N0e0a9795qV|WYH*=dh-gMupp#=B z>H;Ng!GYO-))aL^c>)9Wmgo^xy<)_ms@9JaDZx4^t{jI$Bz+te!IJ;{VUru8fL5Ql z#VhsOS6+4P=0`P0c%g;J7^qgtNcN>C>yE{psr?XA`OvgNl;{5Q_EE22p4QOW#Oo`FCNa@%V|sG?7bxsWu?EOC6s!rHU6u7AK7Ro zYkFK`xlF0oJi~bgDR^T{^A~1%18NRWf;nZwQ+PYqtI|*Caf7p!H!eCsrMI12J`(n- ztbxzJ7+h}ne$+NFTJzudCCPmm!Mm{`%@K~16ytqhzv|^L6iq$`9^MNg>7(C$7SKe@ znl64wxW~t-EB?%#9N^i*7R#x2T+FmqyBI8)eYf>`88szg@3Cl;UvRKh0~Y<|tdZ0< z#+a83Mt-j?s0THM*1r_fN^{ZcN|?&5bWzQ{bS@!;J^y;W`;<|SsU4o-=J({mI~|Tf zl_TApb$Z;w$+Cq!_x$T0^iN@?Yb@5O_JV0nJzwp^b0nuOb@RwO`-yB6#xpLsVPLk> zE4$PYHu+Bhb=v#~CKbVSKX7@bB#867UXG^PlTx_qF!}dBqW2vQnTVIt*}WYS1jD2f z(-x@r)J+B1jhJk_V*15VBt2GezcIgMwxBCZGg2XH2cI=3O0dy1HExmF=ai{*sCCRH zTP5C67gFLE+^>6*B8`)|@dcwsGi!PZ7vRCImDZoARlDjP)G8n1qf1 z{OxuqDiW+0$_^crsjVYRrDANLhD)V%4_a605n{EFN0K#?d-!5&uOJ1$G$`{h)1X-H zq)fLZ;5qv;+A|*qXbqoZ(ccop@HX==yEBJrW4jtS<|@oH+G`A9JOpD#x~*bR>#h|1 z_uWK0K4Vgjz8nzBnP8e$GXkgbY9(pEJywzMTWL!QqgKy(lzy_=njQ-)o8%}#dCSN2 zqLIf#q+^W}f6tj-YZqYyb3V%{^J?rO2LHe%g$Qjj<}3#UNGAQ;H)ySXg_W`Q+yFj; z)Qa{3r~4kaFIIAX^R!sZ76HYNNnQ)aDaDkE4C9l)J?p66wZmy{&VJJ()s8bU z&Z4S6a!Gd+pen7AYj=objLN2i3rcAyPOG^;e6>nr?9#fqK5e+W>dGq8P3AzkWYH&H zYaI6}zz}m{Hia$V)_vG~CIWmsgOT+j`Jc>@cSp{C5DwFyBL1HKG1#y#nDUP!(2XYO zsL2#g!-jy;a%5J7PAvNQXX7wa1!Px|7$$CR!$~$O5cpY1Ll$7WNDP4RNlCz~PIaU^ zQvCiLoso+FJ-2s^kI{oYOIQBc+?rf7U z`GWuJzLxO&<@oDE|9yK~VB*LP>f!rrq}MHU!G_1|>H919zb4-8^-C{d*zPYIvPIl! zJ#8HuAe*jVp3~ElKzU>PY8%IT(cRRU%MTweol)<0CXrRbEKa*zh@CpTa%d2F({Ux| z<8Z>Iw1j%?uYOHzrJZ?iwS8!Jl>rnS9;pDx_0P?+JUs`_zL=NPyzj-csHP1}bsK0V z^ujAfNyZoBqZ<&hRXJT=YVH%V2Z~7o2~!VFl!Rz)%o9$|i)Ts2Z=?Yme4SKcHZb%b zEdP`7l7n$_vHxEiFC!z{|7p@L{%7M|=S2O=(eIC?L(G5qa-zg^$S9f2KgE=L?r<04 zA8E;W+4~(*-8A|2<{OfNwpvd>_VlwwOk3$7EQ|Q~Fg;%cS+))torP)7GEE}@g5q}* ztiohb7$U-85i@3VUlC%)E}SJgzoUm2ZkVhV*>hl{1?RMIk}M<)sw@#uSP~-f3&AiY z?ABi_xh_SFI4yxWk2qa91ouCp0~PGxf72ZX*x{xo6uz9(AyL6WDMnn-`5aEfc*_ia z(a9*uNL*G>&Zrcea!aLvkY`%y2aD_H0^!*3g+C#Szg4Bp@DC!=HoR-`(eE*7C1*U>2w~d0ezn8%yOUz6&O-em_@noF zG6Mo7WN=uNKWCiVuQQVn0uRUP+*A|~>SQ>#Lx7SfKQnd5I)QG}oiJeJznpVAB zw0n}Ah6Cx(Rv%gfxaGw7x5TPaL6)^57eVPM!g@X-HuQ;n%u{SN)x#DNo4>68GkT&F$Tuc=Ve7qb}U& zj5&iObAYOKeiI|dtxe>wL3G#>GiYwG%;vkBJb?An%mZ=Ih*RbmKb8@rjC6s8o&Tn( zDR{o^y2E}GsBLn3uuC6$+SH!OfZKJfLI$B;`rwWOd5iJK)N6-+%T$gtJz4OcY8Yg& zJWh$}a$Gt66!D9Wm*0oNCv^_8j-Zw12zUVTwwN)9Er$9N-=i{jH<3Df%g^`9ou27+%pbn8FJFkyT{T zd;YO9(ohzn1}1H4UE$L?^S>WiFw%~^t`$|&1?wyw9FLe2Nx?(DH4^3S5uSau+ITvQ6B48n{5LN;4O*%rScAbdSe0E}JKyUuDtO zXvA{^yXd?@EGy=bU~`K2_!uOpn4$3|1S#+jNv8JW(`4)c-7nm2ZRzM;sj-zpTzhNX zq}o2@0v7DAOnQRdyDdID4)M-bsJedytVOV%@NiTSqAL}f)J>-X`7H8(2dPYJ( z2!Cm9QXix_D7SZp!=1t3PHCY96a~2aij7Ic=I#-%a=Wv;*e|-s#&lU&9UlC3B6C~V zv0a}2nB(HVaEBB63=}&j~`t_-^>fI^%Gk? zziS`9vCgvPo03S#hlA7!2Ad-au34AC||e~+DR?N1Yc_=s@D_lE5H z@MLsBcTB}rNu2BR1^LgJS_}=$;$QS-bJh&t#=TxyYpVaQ+flwi9<#*pBn1ih4ZmC% zy(hkF$@bJ=ZD#5M3EVAbYkH<2&k_(tsG6ZVBn zleGrAmA-}zoLtjm$L!ltr4f;(en^M^ zC0HvDI4=sMw8gE9g$V-~0xmERh1N?C{MWhRIeo#Zeu?a;7lV>>uutJwCpWyC<_f8u zJnD~}Vkvw4+%S@fUNa+dzJaUuSpD=C+Wa}g*4 zr@GYZoqq>xjImMO_pwnm7h5wo>}DiwWWzC&J4hGXf`|veF|z{>wx?G=9JMM+Q`Apl z_F=5L1V77gYYRdW3#h$itlHQ+ge)X3cMN}`8!f58wT-T*OT+ot3tPz88Y+%87mGuZ z+iFu)lg`^o!M8#c&AM5&nb(M}x97WN(NC=@(I6dHuK$byohZT^a9d!e4oYcJmM+c7 z+ft?(`}M`W-L?ZvF1`Olc&RyMbKgPy4{>AGB4*VRz91VtF+m@nJ}((93`(#TQe+o+ z<@X=_iZ5bf!AQN%c20CgVxAZVTwTzP(>(F2pKL*^bu@z&72~x}JCh;+@t$<1K5$L5 zcZwx_5&5s?e8L)uDQXEF1*GJ<#WI3$B;B>|uOjhk93V^e4|u z*|f3HR{8*GD z`81Tx4U)CHOv(Su%F!(*IwH4Le`0i38iCq9=qGF7*`1bRW5OrA5g{wis3T6hrdCFu zP_wxx~TN$U0%umVNFN78s;xr6^0+K|C*{rmwrz)L<+fj z&L4K)agPtHacvSFZCY+#Bqx%bBaYjdbq=^@pFZ;KIkXZMVT|DwcR%N!q_2EZiwLBW z<6!`c&rVLszFzZOyq<%#?+nDp&ZfmP3cZ`49UvKTH#Dlg1)%@6K_fE)Z@NHN5&zLD zPA3u-$tpD$E!An({w%JkY?LGq()h03yAVz`_H|6DOViOU_eBJ`+5G`>V9639K0v$$*(E{0vq4Ef0>4i0GI~8!d~mkex)$V%d4V`&3s?Wg`x;BFeP}s?aJmYu49{?oLwd zuS>@oI4pFCpWn%D4m+b8+XMy6KhUnj>%_Yf>J}Jtm)vmD6t0ecve40fc+o2Nw_NmJ z@6XpC*8J5Wt)r96^j_cGgyzleUuX-U?(+YSkObHNWJmwub2wO-{?Dbq7{9%SrnMQ+ z&!3~>-R%JxfT+pIfp3%9o03c>vfKlaO58>o9c+vn#EHJ#+mmL|L7eVUI(wSV?D)J9 zd;E^g?fJMZ{-m?#O53p$_}q`AXIPNiPS{SGY{mXGv+=wizdY_#7NRnZR=&zl`qKJZ zo}Rwj@bR&C>KIgcNf`$?@Wxx;_@BRR`Fo;|28Zsptv&Vwb;_r1afiL2jK>n$DX3RA zyBx$;2!=JF9d);61wdjTy#q1M_z}+Fw+r7GUFq}|ADY)PYGSY6q2{;w9AjIa8im>U ziL?5CZf)Zr2EiEaV5khoM!P^pw+&HXgkbLgx<4o%ZkKcYHsS%6mC2!~gDBHH-$xiz z9&0*!b8N1oS(H1Yz;&qTE0aL`e**#3akC_&X)tH<{A@E{FHUbIk15^Dj(@$D?AalM z7MFafE5@cwh14wJe>c2MMXp2HP}fU=NNjt8^QTYWJy&;?QrxXP1uN|0Ie_!lcc^UD z%YyGgW|Y1M@GJwXh%$$z>>{qBS&?~&+VY~zd_rZH@P^(4cgg}-@>1>_Nhn|j%T)4p zIJAsJrF`*G2rS5Pg6kwS9TeB_@^xK__YyVSR#H#>@y|=VZRl0&ExGMyd#yrJ} zuEcov4r|+2(Dvq4X`u$whRJ^NiCbY)ZQ5YB#6`HTp+q8o7Yse?E!uhp%ghyD3t}7% z10A?a@!Ui!u1|k8M{%LlAm5j;DGh5RtD*cpG0+7A!{GvcgFRS(7f%*cFF933&Mk6X zJSi*3mRbVt9wcs1mCNm+?zO-6vrz`s)97Ln1LK2<1d5W4Y35(<(UxLtZ67&7cxVjaiS06EVeu;IT?64l zuaob8o1-s{*qNp9(&#$rLn4v5KH0+M)q-#D@HPQ$SL68z-Y(aqFwL9dODc6%W)Ru} zi3zs9M2-Wv*WA_y@m#=lhS_`jeMe1r5p8JtNO;Mfk*dYzc_fgRXZ^wE-V(nP-k@cOw!ci4L3SwZ}%`w;0v3 zxkYoGI1Oy6t;atKZTpISWO(Hma=N!t1g}NPhs9vY=7R>rfqzAyEHQ9}1Cw*)1XIK- zP4q!m3@CE3|3G;dPfAAoQ45I(gzV*{KXJ_WfD&7C)hM>{X>Q3)UnNH7J8tEI%Liu;KpU}%La`79%q{6W;4ZyL8)2^6?I%-L>TYZk z*G@5KzR3BK=;LU9QPvMd0XD?)uFARii*n<`JmlAb+LN}mQgyc#<|@*#x=RFdossw4 zPml0=jC!>V8KXRnru+v{Mh;qS!3eIqo1qWIwn=S8KUIiImGIdFltz4(?VhLpT zp8?=uPHeV6sLmx{SJ=SK>YhNPOU{Y(Z#Q52U;(v46k%(`^Zk~iIhh6=-k0IXY>IbBn}Okk?LuBAcb#r z`ZU9={m*>r){eiz51bzmi>S3$0sg=>;%b;(j;ZK9p*3zdS#Z!jSA{2JoKs85zS}sQ z{1I@YOH|`fI*H7#sOHEqx*x*8U-1o9BR38@M-R+mZCj4(i6{vvB9g;>N^O}t-UG)R z-E&i4vuJ&}nsrZs3v|bkcYwHPO3l!Jt>dsiN`;56rI*TmSj1x5+fg%_m zao3&s`1C;`5~OP;<4G9eegu9xiObZ@NmSA-dc_06AtH#BwcwAFU?E0;@0O22_l>q=%h*#c z=T4a|rr!HSn?uJnQ-1($tUQ|;&FYWVP|N~C8p&aw4P{7@G^4$)0@=&KvE_!m_oxf* zs`iZhhb6mymQPB$Z~kk*V#BN{T_es@B6A??OkwWm`FY?uA2zQEMKb09sWG}xY`4ix z!e-rE16T6I(WUHXVSuOx$QES2!ZAFWiCsfjc$`Cu!mH6aE4l78j{aOxDihh##Ek8l^feS06}*xK}Lys^oI zYg6(yR~r{dfO!OPuho(3=ENRnLw` zlprNlu`h>oeXkDAl#ILyCXq{ry2u1fQ1Lp-NVCKeMvPqxXUBQc@yQ)t*OhF=NG4}G z)bJc^m@#lFzefI)417zdw^#CDJ)}gpmtB?2F8r{YUu z>Ron?aZLp5q{}i_TA7>H;+BPNWR%+sn^TD;t_&MpJ^aa}Zl*g9f zq1>V3*9ua^L|v2l0%fam;KpiJYB*(R6aI_%5u%a4gT9}PF>EY>wR$P`%BWmbQ6WZm zj;-&XtR@*x`#YOSb2q3eljJkkoL_dMQM}a8kD&p<22Pzh}eT$w|K@fJyR?1_4e10kjd58Zs#}asMzof3x6oq7~&-6B0{7pFY>y4Ax{rCx&#fd-a~ti z#WTk?-+L%Rkcul>&WHSxhi8N22<@PFW`AHTX!e97zgp6Nf?cU%&t9Em!K%tv(TED1 zcUG?C(^Tt@nruj3yc|F&RRCRg-1OB6Mn(c~%GpD4?HBca-9R5`PN*wU-;yaiMWQ)S zMakDqfj?S7G%fk^Nn$=?z++`e>`N&(kT}U^*85G_UD6ywz#bN*E3Ux7=Dv))XK|c< zvnN;usD#69<)BzY2nDxL<@2V9yjjtl7kuc}jSG=C*Ybm(>okH(LV`7H$L0y9PKERt4X{j0rI#YrT5Wv2_iV+4NuKOnXXoi@n;~p64Lou zd}B@}4rAKp%#I>2{vE5CRk{tC2!3n)VQZX?Xl6T+)n3}~7%}2_bZFtxWK9{QcsX73 zA-qV@v4N2I-OT%|ewrdjM zO2M>aeZfLdu{^_3_`D3ica{+_7j=%IuzEJ_Vr%br{}28Dc75p-heP&mq;1=JILp#wfmI$nX~L&$B~6~1-TlT^csf=SOM{JBVtkJ2n$&M^W_5NqU6WB+Q$dGRi$^%O z+FD{|`=Qp+sgJayi-zJib_^gd!L!oEyDV;f%98)SXTPYYeJPPSw~w~Ll*F=|D1X%K zeq%D6S@1_K#>e)+kFi(3m=;6DR=p08J9!lLmN9s5=mN%^VJ-1r>CcICkqYwetVtY) zyW917x!IKbvp%^4U5Hm|9zasn0j973sgKu|y4lo>3NC7wn>4j?jViF^e5TV{U`%Z& z;O<0nez6z3WJHu%DL%1`BJPIpFC5~JjmnN4{ypS#H(Ov0ZJO?{G1{*i6YjPZJZ{z~ zRc~>Ag0Xbg^^N79h~c!AKR4c?Z_K*jEXaxLRV{UuIg98V^eM8u zl+Wq#$ZF5qCp!!a(B)T zb9vA{^18s*Z@b#(WFfDmN`D_xG7(+p_}=q|FY5>|Io}e>ekjSJyE!m=8<^pF@%-6% zTwoNj&7Ey>(gav4X6soUs(gqG8)b5K;+?b#O|*4dbOym#%iktCcou7}Tq#TcxAlG| zf+27{2_}Id5as#X1ht@4hz6`>t-rA|TeV$DWf`8AxFy*B{=Z!9>_l1Pl1#47C7x|6<$#PUqV(ob(3Q zV2JfkSslhhsPqxLl8 zw_c)IEShuOi^C{GuBz(JrRKc5zGMDB5csYlA;4F{woBInm&Qg_gf6vhizLtuud|`_ zoHZJTiL9+fZ$CMhjLmf=>aOrO_*s0ctV+Z)w zU!eD6ok8F4%i8n)`R;jN&X&D&{d;Xi->$_*<@odbDU|^T+_v;;Y-iUFa+-C2LMnxF zvAm~`rtsOPd};fOZ048F(;ce*3W4!2$AZe^-?YH1VCvHFHf2EZrYch)MWMyL*14T^ z^@iC8^@)R?0tcsHqn_=b(ATp60%@u$H^6}w)ZvDa=vUfus`fuY^j{yUNiIHJ?Z`T= zFMxuN)C$j;G6MMI?c{r! zdWE1a7Uv!QC4S-R=8+8ecMjXK4K!Hl>a)3~T^sY;bO5X76JPS3rmzB=j{_-9Ka)7S zKtTVdznK$?q(Vhq=bPF-q%Kpez0B+D>~CA+0ARHMl6iV6qRLO1y318_jkjEo)W123 zNK?t@t?G2tJy5)ZT#w6fTK$FJ!pff;3jqPoOoJJh8i{Xju5=%j){9JZKe0b9-pP%2 zD+!L9NwIv|((B0Bw?O)6lfR*`TiZudXP?2*e=wyo>HTkJ#mK^usx%6T0sM!2Cgu4b z@>zn@C5B+DSXo9zWggm2(iu!%(!q=9>pSq$A!txWT`g8n;nRzGUWW5&vYP(8t8ARG zr|h(K>RSWLcXo_W{4}!l?M6!f>uWvr+lQ;l&EOpRcKR*+s2NND`z5n;h1iD+6ODMMg5+y}NH6*RPT0Doy&z0p6cEjOG0H z3zd(4eXGA#PxW5EzJ^?9{WZ_s`hL1sfS-%a?SdAWOf}|(~cOwKqIn3P&qUqdU2+jmKa4sY2dHNG;?K3cr<{$iU=9$VcFNnKZ;p!3? zFI@$;7V-S%;;22z7Pi*jKKraSc$hc$SX?|QgkCDE@v)M~i>{7xyr?tBANzL)C*ynS z3~8Xe;>00P?cp#^yWI3_L47=h)l&p*Y}eWD4r8%9SPfHv$-|lCC@PM`R^NZc<7Crn zQr!XbWklmM_2fj@-13bcG$ptbyLRJG9SHss{M)r zi#q075dexKgq?-*W5mAq-ty;7?r9mBW3|0_4Uxq_Al@EYmT4dSQY6WCdMLoC)aK2z^vm4zqvp6m=Q@YT}js zVJrU+iIv4}bVGTbX+D-m@NDV9NTi4WC|cW$vUcchB(Q6!U!)%scy2GrN4Y9*<%$a!5B{H;~2^4Yqghax>^4fQ0oI` zcC5Rjd_%kv{u@R>N}(+~sB4?E1DAkf`ft{9;HU&;mi1yvgghZR1kP~iyJnsQ5TeHb zi9w#x%7O47vV1sMJwt{e>`ss`ffJ_5b3V3*xB%wWYscrw>WGYrlNfDXganrY{eaTu zVm*YMT`4E7Pk0&$(;W>QsSOiD6WOQU{o0L`?X-?$bQyciV>_%#yxg|4pwowQ+IYr1 z?8F75TZX@~QC@NUW+i~ehcn(0_+XA3NpvEy89{FE2!$RW#$HNPrk`sdMe|6-HB@9a z`||9%OS}N*@&}R zAtIx-%~ZR1bPaEnEkYZna8=kpfXMA@xpfx8BqtjRH5s+KAejs&Pm7g_Ui04xFx1hS z6==bE5mZC@m`L7xti)<6i9x3}m%C$HflMhhx( zf=`u2$WkI37&=&47Dvob2J8*x>8M*xv)@Wp2<&@EEFmLa^Bo5vRI;IK)w&C3?(bKb zAB`r}2oLe2c-tZ|I_eoQCL;dSqJUCv<#y)&)THm$Vh!#<^G)ObPpn9_B2ncHtIhlZ z%V$*@FXRe=5`y8K5IQAZv1g+}r9w%@nwTBfm|iXeU5cOWiHnYX9h28wlnsujoI!B+ zCJyRv|C|4+8#SKmR<6t#cg(z;D;fom<9A4e+ERlGUfhE*n5!^2urLc|ydvK}<@PMI zE2AhLLrmffD+|E}u-WB|>5*v=t-Rx~emhARn8)n==ESl)oFv6=Hp|;nW}cPV6&Ij= zl1sY(ZzkR9!SQDdQi(*H0iVhi$uBe(QKkB3Z{6JLXX>xeR7C~Y zxV!(!VNAE(+0BJcNcXQgXX|zLG`aCm0I>?nn4I#lXDu>^^O~))xjVM=~kX8HAHoGSL(&DgPpX^#(tLA?;2?B@-X1z2E zuxGsIRO_i;`P`W-4r03ZUBh18g5*Rz*7C z=qvHI!BIq<0f-G+OL-PwoUZ`((EYME77Dw$W8Ag9anKguzrWp`zc5X-CpGU%cBA%j z{eEH3{-;~+*xfvqiv&$d8}V3;V_whx)lS(wX8z%|kIwZ&r#t!oW9u!W;#z`sVQg@B zg1fuB1=m1uhv4qcBzS<}Fu1$BYamE)hv4q+{!Pv~?|bjM>-#gSW_NY>?s{g`Q&YQl zmyTAkN>J=~(#(^q9&;Hy+3qy;O4rDAae4+qYm|^AUk`1%2tpH)rRTyMck4gE4@6`l z3$|AN;hb>`4*8zgKQ4!S&-LB)kSZEl8;E+x$g!i7QdQ`2ACgw%ms5IUqZ7`bt784) zmrqp5&Q!2}ZxUWn(}(b!X+;W2OLt2yZnZwRqw+YL)X+U@mw15-?M8>VuVJu0NG@d= zdN;NZg=xaX#gxnE>a96cGnjb-lbqB2C^Y}D)}KnhauN61YE11pXTXv(67Pu>h` z@RO&`4Vdb`@y3oc6WcJlhVdd?iX5j09ZFJrbv_pNLtYS+gGLLcG74GiWFUgSy6nj{ z6y;u*=miDgaC{ZKaTAa%@vs&lX!%B`xsBzC^n!ow8js(yJ`eaJsfR}i1c(+u0wKMF zPAPWX^K^)b{=k&##PMbfd7r3`U1}mHypcxJ)7TfBSEYGbgRX$*d?}BK~^4kls$3`Lh z^n(TcoG+!-4;9M>o;3%nACA7MP6#(g_n=@{EgyV!-)l1HHC~_&5MeVa6Z1olh(;1A zCS-sfCEO_*JX4)YqoWR{0@J5EtEuI}4^iNE1pH~SP=0RREGZTrNEz$ddV6l>t^xdu zy(86#JQ~@WmTyC6KpK{QRRa01Oqtu`i?dZUcF4Asuq!4lr~FXnX!*Q_A&)E(ZW2W- z+t1ep@Qm)U{*x+~K#NiJL;m)Yx?x9f`CWWS|C5RiUHEx&63xfl1f5P_LGyZ&Ci!ga zzzmU$R9<)=8wgzr8b8TVLG3U>;Hw=H^Q9<0aN5bhcEsVX$*JR;f3zdrW){&G$l78- zDRk;r%M5An(!yc_KC1P-Ld6XI)lSQ@PSJ{)PN<8Ewb^tz;8VpC-xz)T2PqnNgOOGJ zNm(^o(~;`yqq#r~sJ=3`L%6wq8Q!isLEw%!G)vaXLm+kx_G?tvAMUoj)ETvSF>O)z z)pBL;%{DyyX7wro;kM?m>yu=q3}HLd!=zmxnk`4}y-DTK&2Hc%s}bN!G+)rhM~fkC zWDZvw+~k^dU{B5cclO6_{Y%30{gVUBO{b>FN55CLag;NfpYAs`aO^}5cKzbW+uL~o z#6tVU(A>~T68?&(P~rHj(Ce~+lLjnMIZfYtV@=F|eCj)BP^CUH;HM3sA)cJy!1|du zMypKlVDIV4!mxCKzG?kX`a?k9t?okdKZV5Jd-xMzG?sy_+GQgyAQL zfW?Gq=uW6`NMp#U-tl2oX6x*Wau$|2ACCenqPpX7up=owOl4RGd6HTwhQ5Eq=RyYB zcEs_Gl^OAFX*i@ah(b|0INJ?b2N~FfvpIBnecSsJs@Nab!l|MjvAt`)la~j)T%m#% z7YfQTCcu!|2HoxA+-lEBme2AB0Jy+FLR;fjy!m;*UrWZP`i(?F4i&%Lzbh%<`{&XC z-a=YD?dqC*j2t;;{B=wxihyOXBDwWfVQ3D^{eUyhGR$OoQLi?FbuF779rt-c!?3PU zQCfG-7OZceP5x%+1Vh+C`WJ(QhbS0Ll?{(K7$6h5;KOlWkOLM)jXp%_NJ^?y3ZzG{ z(%nI6EWul{7xse7xQlQ8m)`|>`t`J&_mBJmS8|40NJk7K!eibj9PMNY1u0vfm$CP^ zk$yKI0%FGR3MO>eTB&3^nGodWq>CxEle--@1_gW6|9D7tz{_0ZtD*uQH$DrWzHJ0X z5dcF&Blyn3y0FdnyDI@x2c3t7=6L(;#AhfE{|9ilO`Xfe&U zq-I?ydOQSSWK;(U+pRSI(C*d7`KU(}` zt4m=i&z>=`v>R>gVbmX&9kMjFmun(1&1f=@9z(R#nN6di(jGlFTPMz(^igNYbcs-P zKxB8HkEktR?hm@Zhx^hmN?T){Jz7qdbL2>;M>+iV4(l%fe}refpZCSxO0BV(0zbZ{eM zXXD`c_p7Rjo13|d!`~~spoDULe_OOwOl{1~{?X-c{&)%_0s~^#2h2dRasJ%` zL*M-M3Wfm^TuX|+xe^b63<=&A|2NA3A{GMpfHc5upo&`<2T!*M3A83I~Y2U1sT8=w0jTk^h5?I1K~Zw@HelL z1CSs=dQV_Y)>jx$NYMEcc=*XTm|viu&tT22cNl9B>?;g?qbh(JJkA@qH5(Gp4@!Oq zkGMt+cuArK(1U8A0q!7oNB~{45)1$n5@ZGizTF&JKno}g8r=NV0W49%02n|U^njlr zL-6aQ&1A{|M@WzeEcoI$0zeBy4hNQ05CNPZ6nJpw9wtB$r~m=L&>YJQaEAm@A%aC# zRseW0Ul9R}AY)X(BuEVjtf`F#aQMe;pmQ|91L$=c1|V+9KWun-|6go) z`2NL)hyVY@hL^3`1rs0)1IYoZ!3E6zUwH8TiwBDVzyOMk7xYaEyvE8~7<*6<9)P~- z13(iJ)P@f>1{e}tNRSu-c)6WKe+|7z0KN)F2N4paNeEzQ5(D5vf)a?pD+hyP2O1&< zuLlfHIp~Q5!1o_G!erp)?spg~&=eWqFAh|YpaOF6j2BdZ0ni}@xCcd+%xK^DwlO$T;B4G4}EJT({xJCFh!_}Up5 z2WWP7Hqhl03>`EZJO97ixwMpGX4ud>@3nT|!+cIJz3db|QP&lMb7P(4;M|xl`ulre z_dwQ{nN=uV_ZhydiTgeNxtSO_6;f0mSMI~^tkExA^yOn8t+1sy{e1;qMCiCsYfjLO zMkt$Xk2rG(QM=RyivNZQoQ9vdwSMBT zJdW-Yp|L@1XP|<8@TIoANnZYD;T(HpVMb`8H(N}t{M4aha2wpyc;^T=&(I^ z)f+2(;>WvZfMsNqHu4o?*FZQF(SR>CRVin9d~#xUh@dAyuli8&$@`c_zJ*LX+ESeo z!v;;^+$}oZbeU)wSfsdd>GrYz*>~N}b)0$usoJxVrt8xw>_3`faMz zt@Z1WyRT#VC^#}lJd)8$b(?m+4WzB-Avd4Lg1xjQr~4~BYQKC|di%V9C#^=(9#2^& z;_|bA$Am)iC+DCbHu9T0t&~ z+K!#qm5ewAd#?!{bjO`5*0JRfG_zKo2h{^&(D1|c!S2UOwB=MXe(Gu)$E7i$PGV-6 zY15bb37kqql5}O<55Z4zdBnz54bJ1?+mKq2Ug7-kO~C%b7~PijXm$F+@oc6lFQIEH zuG(+khEL(ep{6)aU2%ME?|=x%^srFI?I)TmkYpbD z|N8#)Qmx!&qZYj(U{J~{(Q%E+i*yqRbQkcA@l>ax$HDn&(l7BzN0*p_8)y2;-Yos) z$9-6xSvjy1o;46rnE>9vWZBDEfgq9PYtZ9h1IsPUsHV#A-v&NVPpw&8&%Pgn)WYI2 z!YAN0C$`5&C5E0eGhCMqxfMEwNFIcUctWO`1oG7V`WuhzPZ#)v1;?MwM;Zpx`{7pz zE0_5L)}-dN&0lOjyTT@)jB?O&7|#1ww|}{4tHT9;@ogsK^>1*HvXYMVXGb-oj*;-a zE~)>mCdO918$2#CjgW0!f>W)S)Z5V}Fd#!gpics5pQ_xfvsFiEoykhprGeCIH!om} zeh@}(l%IqXaA2#|Cc%0*?InYXHgt>_WvCB|57JAJ72Rg zH^2@Clp+K`0kz`-20{4ZU^fN4f}w{5Re;66gy{#mk^nm=Fio0*Vn2di?gzkUNDxp8 ztO$0=V3x#?279@8QNRaCkdX}7wP~7zSyD+B+#7rm?XM38J8NgTzy9wP#sdAT(9*Fkps6 zhXmQG0vP}L=w^`6C-AIbAKeOCRs&05hU^8AeFiInJ+l*-#Wlbe!3?Ph#m@E52HC%E zngjghZ>`C{G+7ME^_Pz5|8>=WwZMEt_m?Y)A;C=;s^I>A{WUZ@Hyh}iG8~vV&;a*P z>>U3W4&2~!3I8X8Vdv)fe^`>8oAW;$xc@`!|KPyQ-8`rTuz`W({Y#V6AWbvya>3MS z2x2w|PYuSv7xWGBA6^7o9>x;9vVSdK@mBzpTaUNjBe?j<%!uOm3rjSs49RJYT-%y1e znw<|Ev4Mjp&;*z;q4>B!;#T0h&vpY4LV`Y7f=vyk$La(zG={&i$vreXKPM>88qA4Y z>|D*8o&a$SsuzxdLAIWI((V^Hw*Y^V|DSEqd_16Y5qKFGPELMa5V#W#P|w~Kn-}wK zyjpe6U+xI;hwizn)F*Q?DzJHtuUupYW5-H=!&6)QxS64NSQm^_|pOJV^u&xs_>Qf$%#}@HB6@@9q zzGEt{Q5FVH_j`io_d!NHAaoYh=inb4;bJ5msIcek4KOz`kW(VYUaEOiK9Yz;>~L;p ziBy9!fv}b4&`6(@==$JPHPFqO2YGnDxrDF=U7aj8!ZO~w@jtKtnr*x5#!kO{$ZefcVgP@&u3 zOm#>Bg%ZI$fHA&IGrlza!;VFTpK@7kS?y&u(YmkomyWJ%iSd5n%~!M*ahmV2lbj(; zB6cONxn>Wh@Yc|BLO&8=2Y47%N3xRPRWV;kP)8_kVhF#D`2_>hpqbAoapfdmH$RAxA>(=E(C8+ljerHgebQM|kkt7>Dyx5&qWCbgoU##G*) zc%w>w1Zh;xz(!c;!mm5togA0NO;tXf-~qY z@L3l}QgrBaIo6DQefd-~Me+Ky^SR9XPp4re?c>duwTup$;J8WCkwrN*jqbD0H1ob? zWM_2Dk#*3D$3-?n#T`tNW(~(g_F2&mnf9A>Wd7va9tYG~Tk$>`!2GHR^eO-Fp z&(((av*HQxXVY!_`R-$AO`+u6Nmi$J(o^5zNukZzDBknx7Qxc4_qEb>PU~}&f9ih5 z0Lgw#Qf{pr9TU^4=`bLnG3*GlX>5Ninqgp3V{GBN*fs4va(5|`I!$?>^R&@V&fTHZ zzJn@M(+H>#*eB-e;0LbD-mzq}e|Y+dw&kL5`b0@9GvIdb^kvSC+rX4Lz3nmqCixr)TRLM-31v`lYhFHh3iET^5%+v`9v$vxyiLmD%(Lry znOp)2Sn|Z+wuq=a>XP$~o|DLsdLKZ{7DN^+_d0bSE|RCTIh|>Di+Ccge5uSCli!gK zU*@y*C^$GdL(S6owoqn&N2AJ0+hzvG^GKF1c&@ZRLhxwX345-9HeSBt)$q6^#IR_< zW60}CGg6h()_Q%=et!0Paqqi2kw7}`L0b=`h80O;vPv*VyYW>?JsrC*uJ5B*>OAZf zheJ_2=7XuQN&YqL6v12k`PA97rfkR5$E!iDM{MlMt4>I5Y}w%(iiJquN6qf9y2Q+F z%Dpq-wfH_ao!Yczc*aOg zucyHb?@Q|f^F8j&%$#4YJkzWopP^7%1@6q&x3pY>AN56(51R$i=HHIe2NM#`)buhO zZxa_#Oz(@p+flj&bnoI8itHZ?s)E~r1;-!!KDJe*4Hg``_{q0b*&n(0m_8TyR)0$t z*U~zu4D!i5g*$3FeXaD=m@U`7F`6v{YFieR zYdgwmIY;#6f8hDiP`|Q`I%^tcf2OS5eHhVlAt->ozS2;m=lbsD(!#`OS0LK85Jyr$ zGdREw`_%eV=_MRePhjnfRJSOH5GA5gs zDS{A%Bt3>9-iCc@FLZ_odD{1Z+jYN~#t$I`2zpQ8(;8jhqt?wiunSIU`{ZgrW{BAl z2A2B6y8VS?b%42ts%!5$JEXV-t?!0DI5#?4p$b z8j?<-2!-Z5g#QsfWuh zP;7sYNVNa-Si^@UkH0rySg_#kttDuM!GabNJ^9?zUU<+p_KTKhWCKf*zDv!2%QRO% zM7n)U?d9hr%N!gFy?s-s5m0uKAxH(e@IK@S3s1iG_97rZxT%?;`(5aOb{K9-rH(Wt zAin*>O;F}bgP!94bGQl+2}&ODmUAoF0;O__t3o4Gl-|kxWMX(sap#Tqkh8$sO?fBx zc5R&9;9h}wUf}avl&bTar<(94Z2|9va#is&iM5Vdw%x)aZM*$R0`T?2^G;2Ozl*+E zMp_F4elblo;sAjJ{Z=4({1LmdlC}M2+Pq<)Z78N4iJPCCy4A&GtRswyFuvB@couAx4j9)yv;x6G646VWZg)=%>eIv4NLW6g z#>P^WNWryqTBVKK0J*lgsqM#rdzi3Gx2a4va<35UXXB2h4%r{dzJ2DbZ7Z!b)vX^{ zl8%jiyqXSf)^-}YA#7NShDLB+9*7MZcBj{yKL1jHJejIB=^!57J1Q&xK&`B*I`;(xblN!sw80~IOVbl7k z_z2m^;C_zOiUq3fOE%-ws1c7J*(|252+gdi-<3Dkn16C>QHnwefJ;9R>d*{=S7hwv zxnEn+5EzZG0IX<_HA?nT`k7I;=#(XcOE_W1M4)*^a_C2*FkDk&%S3&$W) zn7nzn8QvfmQ(i#RL7+7pdz2Lyz3-faTzZBH{&rGS8T#d3I*M9y+Lv=6p8Q#96>Z7! z$ZW`OVWk#%>HLG~aO@k4e}5&qLMXNusVRz_Q>eBi5VIpxtye!xZ6SBooz9(D-e5nn znxucWyyyN~N~{QCKQbsh8_{%43Dazf3l1XnHpMQP@0mTUXx(x_yGR9hTYoK>&A;fO zj_XqDL~W+O8!Ld|?DM`&H}~ks8H$~`)z1mPs-+>Z*0ax<@anw7VVKsp+fgGQ3O}3dTbW5 zexS`|?kEDx^&9HhFNFQbhmLn_1>L@r98}$@NF?#=I1M{qD7sbRBivT4u*|^Qm-Anw z&QS)_&i(sWjZObj*QJLg ze-8m?-bV3eo~+`M1Oqp`phV^&$E90|ji{DSLsqcn?y0xGdZ1<5qPKut(&4~U)X(tN5 zh>W$gD^leBf){6VCzXAJR*naF{(B6d(It(diZYF3Ey3BCN?InVXLp-zx|yBCh{pA6 zot~dR&+2(vpTj&e%^guUKLGL*Ui+?&VwVK(S$(GpI;;C#j9J!U3}#G z8V?=YQp*D?#P*5r6t29b`W}CHY~E^;+cw@&-ivA0NmKhA9i_8s^iKK^knS?{rR!;@ zUc9HYJ-#pMnlt%E<>eDFBm2NA69~_Nj~3mVIuWsbvj|{n|L*gmDEvM&^JnTr>`QNy zW;?XgwS(I^3;xOCwl6QivE|KYdkBy3+e;yM=Y-O)teIOC8-J4&SfHVG04nH*6o9DN z{ySh39oY#PhE%lc1+66l^7oZ+PG*0nxxoKJ{t2xCL5nS z#mBGTxJKcnIPvKuIn($hp)quvyrpaCs8KE&QDpvz6`&{cL#FWNj z?^Q@Pn1CAbc9p!t*b%ja-eZhIfKX^$BJfkMFOf!E-gMj|oemw2VL^9ue_Aj>q7TWEt22U9o^!F*kgga?eYMVKp}aI!v>lBB8|BC<65B#q=8 z9r+rCem>^b!4jt?aM194Jj%FQ`}JD%{a4^_AXihIwWsx=3OuJ)%-5&oB;dYEm(D7sSperXW%{5H95$fwG(5eyy4-*1E-U4!So4tY% zZ1fm`Mulv;*z4UOUlH1fO+fQNLlr0UaLf`7BiWuLDJHm^6%DwLpA#)Sew-iAUbDwM z^vN0u4N!g+no8}8dtp%O^RSy~7=iLW3u`z^a}2eWEugk<(DyzGizAZGh;6_y-Jo~h zj==L5{Zh*ZWE5uHt{g5^vM|-<|bbjo3`L%?Pd{wtj zKCFjQs3bRR3OhZ1W>Z{k1DDXtrT=LA^booBcD?;g>2+(VzC-pkFS9+jI_4PI@s#!U za%q~yJCl7ZFotKArp9@7mzQ*K3*vFt@W)s$I?Wg7LKc{uP z*`fB}dB&pdJ~xIpx3nbmiZH)+@6l>M^t58i>NdHen)fZHQ@uvx`s;@a?xkcEU96li!~# zW!IUm%~K~G$0KL$>gM#)-)j;sj`Lx3ifafgLZ2WD&}`O>qaj-#e$N&A9GN?Gw~nls z?E9DF(E2o~7_3Gah+bD&%ZNnnH)6`quRTk85%}{j#HFO|&CVzM!JK+cDrt2yj&LD` z9|UeGU5J!5`dWFryZ=)6%zAPMZ@7PXT77;(4}kf$5jV}!v_y6o`!jL7t0Po*g9t-I zTKr;@hxn_{F6@_XY1SXszNyXpx3>(PO2;M%1Eq#2r=RbwuAH)-H0G)V<@;}2PRon( z9-q+6p3Ikj9L5_G_1{iAf5$3r+{469MCJz4yu5#~Xy{SKfDSP^OZJc@=CkShHeOT} zG9Px)ooIn~1-0l;GLex|b-98m zL@>ziL00bxVnsU7s|w!%2d_?>AVQf~iGGC-%|h)&cG5xh+=Y+*+NIl;l+OSn`R6S# zzhj@A>jTK8o9-N=s|??POn=$5h+7f$=N4F0z8JA8kkB4*gd%&h|-|5XEa&VssV?yr|a+8mFb6D z*z*@6W8CuA?oFA8)0TYYEHlex>1EcyPB@Sr?>=+em~ z4wlA`B?;T9icP|HO`fSnH2RZf06V=`?-SyCVRVi|5}2m|$S@7wMyK^euj>G1 zW{uu*6TbxD???0WqE-RI0UJ)#bQ7C-^+tJSB3_>3GvU{1$&@Z7O6lVUJxRS!Ba*Xt zaLT48{8nSc#3)cz-q;#^Yqj{$Wmb^FqjjI*0 zJdDH>P6eGvm7m}af9GwX{?bqXYN%s=-5&soH<~4(<|=-tG!s`)x=^HymvFPvBr41K zb06QBx>sv^r8GnC@Zxx;Q6RcfotKa&a!Ph@JUw@Sj_RUkQ#ut+%JL#-yE(UzS2T@T z%4+0q(?BLI%Th2*FeT7#6y0*RX7QS)o`)vUYgoQL__4Qtf&%e=BL+R>9pc!M7VE!w zi5DaeemoAt#mUbHa{dm$X%;;M5MiJJ!yG*MHwPyi-(fu>G;aQjkHCrdznS#r;wL}@ z2C4~h>eZ^ixLWjFmD zZg&FE_1}Qp{Qm@8pf(>!GEfI8ECEnw-EoBnGvMB+cks@HK3)=am;yew3Dnd>tlH1N zVgQ{VyAZ()&O7V!M_(_j^G-XAJ1ij7ABXLc*nOIf%~-!iS!mlx{B%-rRk0|Ygy5*G z!&+Zq7r}sEP2?>UlbpX^p<-#vHbu>BlatvE%?yStP7cvcY=LJwRXx!7c%bYlHk0(TNztu~f=(WrHEZ%{UnN>=HBR$jl(t;(N9?LZ;-SD%NGU%bp~d&evw|R zTM_q9@HSg5ziA7(Z_qhz(WNQ;17VQS=vSJa(jEd-B!cAF+Y?%G@g6y*C~svJ{W|#U$_Ul+sEuV4H49uc+Do3;ek#|CsuVe{1X@sbvPFvC z4Q~J06p65JQ5oqRpe?`-c#KC@(hLR4w&yW7`5h2hS* z;l%SZS*(oWSfai8j7U#3cB{+ZYAzFhT=-kfnK6uH&n`d8CaU=YtNmM(I&O8ZOv(AB ziurNMiEH8Vlg}M0cy{wBkZkizKgBULP|ZoW%#td}G8OKS+kC%PbD?d=W8{z_UL~c{ zm_vKj5GATUGS9a%ys{OJ9-E}+?S4CbeVDn_j`>kH6I^C^w_37O0=mE`rN>%T_{=V0 zpJ^2PhN+g&Aq0#D3Wo)FuS6MFKHUz2%6wKkNZ$vqj@vaT_p^9^s_^oxw%{J_L6>Wd zwRICDkNJ#W%&dr})i=F$0b_`Fu?r-a3%TWBhZYIiQ5Iq6dhPptrrcjUm>m}dd^ojC zywf8tEH-$8WS3K8pu1lih;v>XESjMAPRShL>eZCbh6UJx`DN$Nn-v6W@JM$BPpwad zPmrv#t+W)kYB#$TGx2s(H4yhS`6v+b$OTxlK$n8D?erOpc1@sT`^eF+ddnGtxyaqc zI|Fz9*XudftNXEEd{y)78XB)AcFAqF1Iqy|6>N=&C|HT>gAeTFkk4g4i?E^t`i!rW_gXX_Z*hVG+Qn?!x=@xx z>KX;G(aU;oCGmYy`M~PRC`8FJN2)*si7K{k7PA<-4b}|=PuA_YQ8DP#@{ymP%L%>x zk4k0~*=8`VhsA{2^!%y$$*s#lbrq^P@+pNW%vhY)fjM zy7lL+NL2Wf7YD({2dAZu_O6LD&}bd!^mMB)5;8e zzqdFVV?6${`h3$hf>AHW$l+JK%V=f2!Ow~$5WY-!*CeV%imeuY65tx%?5%Kj5xedA zT1dNTI2vCk(v;~}5jKbR#uT2Qo7%>a_`<=;bva( zu)}r9?JuqFA>8PKOM}%)M2;O6+R(9b0lya)Es#|2&@DRbssGR#Jvp^@9Vg>Bt$Nj0 z#p)2{1xZjT(-3;RV26sC#4$RC6-!xsT-keV%kSjR#`@x76kJXc3nbAxrNGnQ1^yl$ z&Rbx%2<03y;D4lbnqzU9{T#3p=nv;DYsIBjThbep5jiaU1daG>)GPj@W``hogT&ph zohaFz&x$O~K1C@j2wO~+u#NaEd-B7g0Dq4-IIi_vKTk4$R3oglp%=@JxYt}S$$-fA zFy86AHGcakskQN)Qzf^xwU3rQ$UrZ<_`eo5~wp;-s}l|`I(=q{u90|~)6aaT`mDaVbNmaFN=W~A{?=&Omo zV1u2jZIWd*7y6x;Rk;(g>;NQt)cX(9?@-DwwHp7%D4c)ycCbLwfzL<&FG4D$gT;ab z8e{%U%vZ`{(#lGVC`KQ{4l*F!8Iwp{C3!xfbrdG|c?px+$R{6=14zoPF;hur3(4a8 zb4r7sO@93dJzS^QHX-#)zbP=M-{s|!pAY-UA~O2atc2do7!EB6slgCfV(uSc2ta5L zY~d=!FCklJD1ItGx=!q{#_LPM@wedsRyi4J;ouIBW$*64GzhX2>^Oh_?YfLJP{Q@d zVM7u1_8}#;n0H=h7VG||XlPgb8l0;@tiMajcC=iIgL%h|lEo6%wOsuCq*?GC=aY_J z($DR4^A9=+h}_eI2t;$?67z~rh)aZ(O=O%e-@zp+ivXa)?OwL$C)B>EHPl02;Fwg^ zx!Z6ioN#!~!i4G=^2@-A=7&Zr99^ilb(Z-!+~bs_875Kh)kdW4+b@HOJzfvHv6v|k zfo~ z`bGIB4H%<>d0!Gy^22+-LQ`-p3^LLyqjJyY_$vK)Ujqpf!aHqmV1GM<%?HX9(XqlV zD}Lfug6j>>3OX8S=(&}-ogHK?C)<9+%uf_MbRD2?d$CWT{yy44f$2Myws&@lW-0Rr zr1DLaJK*}tkjhAk>c@d?eD;%}R6D(%lAKp_U{?vjbI05Ol z{qSKRR6Uyx_F*s2i9wNmRXFg5q93tL2i+n=OpPaW)tST#krRNX3zN!LFifEWIsPkU zv1-$z+aUAifnd8RK{+phJ5H4rVVG8vHgi1jV?n~ko31pCaKNv2r9~P8o8S(!JE75D zsMsD%TIOk)MVk5|b(SUF6jcgS*pItjBXk_nn0VKWv!DZVfkpiaoKoOOs&pAM&Mz5h z9po?4sjBd9zmzbF>nSAe-LEe}>5fSrp6@T;7E(=@$2gO5p8L;Etg1hM*}ReT*qPHb za9I!E>!yfj5mUN~=GNNAq%KX~5VI$@gGW_F%Bw7K+1}rZ3t=?-_OW+g@zRoJ6jli? z<{&eR>^xh}@c#4z1y?$dgZeRo(~g_EjVFDcWcM0111H{VQJn+lBwQ||V&a+6wFl6Z zhE>%K6>sqX_XvdO6{9B<4x&wL18=8Emfs^PuG}P&wpP%vdmL+(VAFz%3i-;)44IAg z`qhEu%m+H4mE~I?LbywFniGo%J#}~%_t6*0S3-4QU?(0uTNfHI&!FdExOWtjCeUDm zS31`T&h<081>x85-?R#V()xU-&twq?9dzI$ktoX&az6v#mj|_4MBm-6vw@G>W9|3d zLhRmawdae49OIHutD{@(RmcP4MP}QZUe9Up%Hy_1ws{p~Mp*JQND`FH)94gBaiOuu zIM(pHw^C{5(Ks!@QuJf~8;Hag&ETO!v+L0SUs%7_~AEZKODO;lR7N(=L!^c7Zea< z9Wa~5ZF$Fez5W)?_Gd5Oy*;!YZ@&EoA8Xzgv@2QyZ-8e;)SM*jwsFJQbhepL5s-jP zK_$^~{i+rXNSc&e?zO(YpA__ck<>txg5v{4umrtj(KQUuZ02uh3v`cP4HM;#9@@Ev zHhbku-+w1_=Wacm9YHjg2Bj6udZF20;lYj8XmGk_lfoK0mppebHTbyi~jmKWlX~D^WEUm z>HQ|3`Yh#Zmj#M>2vhpTcluc$dRvOwV2z$qp9ndtuD9K>^aaw?Z3fp-<%5r_?TH7I zO$muIo1Y=19|JM8p1BHLrc|8=u!xwnJ`jHnuer39r#@l*CQpBg2Dh*f6P~@FVAVVw z5A;={yU`2&IKM|pwIxEDE8uWLY<)d_NU4HhRsX3*J!J9ss74bG3C46{S@jrxS853> zzV&6EFG{Ol=U&~GhZL_@e{)e{Bc3gyv*#4-MU}u0H@wP0bvx^VPODXYXJRW>OiUf$ z+AIhi&nX{KDdP0AJi$M?jVQsx_jv(3Ye4zC<+yoC)3Wr#qvPUnb=g`?RUOM5nnZ!Z zw1V|dx@g&0nBt(RiFsXhb`-*gvirM0jCunCqlh9D97_RI542fT#fdt+R8*LGRGBZ+ zU*<(P%>-&JB|iiND&g~(GIJ1fL5IU2AXp02nCY!npqmL9bM^LC5D4y`e5~{qk^)vu zcO4Po_?+%AMUh@*$2Jaqtey02%{XDl8A>%HndYge43RWH)-C(y#>s~%GUUU>ZL*}m zHs0HHv4S4({xk^eWnDG19)N5WLroL8Tg4Pv<+b#PDI)J1)p>#s=puiJ5K$}h<;fbf zZ#VBR@d#xe$CsxrUlJ=bL87*5!vkhw!j^~P&yz+hE+AyY>r#ICQOKEEb0zV}MQvHt zW#c{^$yl^PO(JYPw9Eii6|!3^WsJF|?OKPb>0sVQk&Z&fs$K8*71Hx?^^(|&OaD|A z7T+$uvC8Gp#Q-&yz7z_{Xs=G!$$6Oplt720Qe|y!vI=FuS7nXU>w5Mh(iW&wh)EP( z!(qX( zudOnXm2o>^J`LQ%=N%u*PAhyK?POee(U3-T zKU#{R>d{+mVFG(S@iZir=!b$DH=o)~;*=_$7Q6>ci~~v0vahXN1Pefjw-R$^y+ugk zO#fblE;L0#blZ%yh|BUJEfbS!0ULM5(}daJ6OZ_jrOeQU=`39pGA5;a_?%bLONm-x>o4XuR*%=)IaG-wn%O7_8Yj@w!n4Wi|wKO7U8if4l8qp$X z$3Wts3`@I+M!VnMSV-RJ<}RIrQ;W(xpHbrkryjgTdOu{zE#q zG;H^d{9}+N{G~>yCvZAeFnc>dqn4;w{LCMNuv28om>r+Se^tz~QB_6GT&qki_j zIOTj=j7J%NW0?e&D4eh$=@ka59$kO+v{$LltsPQ3k+d-h8=X-rIgB4Ej~M6owlS>8!WGGlIhq_&A3~Sn*3)u<$?&vJypI%5u|B zeX)Tyu(aUGZ@N-+E*b6|*~RPS3?n*%cv;WUJ5k5+!h|Q;O2D53oin@}wfYs6Z$(bs z$5>l5CWS)=7}=kq9rWp5(ZUqFK-pB6Tk5@{FvO`lC;k+=hFErwJn#y|Z>{H(!skDH z!C4k&fy|=FImJs~dSZ&g0w-M;O)foPB&v!0?Rrn2+IDN`gT!Ro(S4o+tvL@5mT|sB zT%=2@De@K_wp#B%lq{FUQ>HlJnm}rh^t#n+C*E~K1EF*O-Y(G>HpyJ|Rp22L0JXon!#&RFljz+hNXg1@oQNrx_| zcd-7w-AQB~Dz7f6QtQQk>zV}PzvPi@@_N5Icwc=kvdZ2lV8BKVPi=(FM5pmxty4GX z3ER_JETJP3WelsjJpS!ll-F0}Z&d?d6c^o{n7c(NA8fw)=0!EAN=C6R^+I=h_vrE- z1_Jk?q2oJ!Aez?HmP_O&ZL%|cMcOreb_!MsoZfnWZMw^O-_BCP>q`A<*qxHWsbK#N z|Ep&(0vO;WM1oBEq54vtF@q5`m3}gGc?@1GV=OTX z%y*EB!Kc^J(%E&H&{VTlhBndBpe;B}J5z$9Zn^-XL~T>Z!zBWXcQ*%iqy?M4-Cm4( zB1>)PNYir<1=6y53dMXMbvNx1GT5ng?9M#Q;7zG1Tg)!l6m?08h(2ckeSR&4F$XYu z`dUM5VdLaNqbG;U+{FL~-P7cXuL=>q*HZw0*8~H7qCe4uft495EoB)eQD7Yk#HR|) z#NbU6-)8u;D2RW`K-CLAOSXKe+f@D&I{pVqy5!$EC1?4}yEKtUz0b zQl8KY-q@m=KhMm^HgZn#^@^TygB9UG(fk#VhU(hgV) zQUk%qxoC$K_@T!-!yvoN}NN)@!7IiDfS{|9?OgujUqf5DU5 z7^bACFLK}c6xKPTOrBvS1f49f%6WdWtxJT|WJF)>#reN9?dB6)-Owb0|Bm~rC ztlX}?D6IB~;V6GK!ltihLaDkER{w5nP0T2~rsL@Ag~R)ixZmR|u8bAwg~g+8rk!OT zTGN47DyTd=(jBnESFfTD5LNR149DiXd3=G0_O!-zTk9CEe;ee zio#*kj~&B-a(I7w2Z}?n?K6C{7ooamI}I%bd#(|YiSbS;p%Mi|Sg5mw5)VWNk%W*y znie)it`rn1MDU7{O)2EKB%ABL#3k8>gF0x1K<*sUC%F<~;J|o11iP?| zM85m}T^ZQ1%39&&jv#vPr^D;N2<}pI5gb~)@0%|s=qXV_-pKTfpqB{VfU&9B4q{8^ z0HUTyDWbaxS`(NTe{MTOBQq2*MR+wKm27_y1?6Yi{5CivM%+5s1vNREERD@?Lh+8h zpMcG8qw&?kp_$*q3kuF$V25y5;4rGY#9MLt=+b9%X8iJ4`GC*Ce96Y4iE$QRf8h=$ zW`8HdS5bs8h~9!JS!|$d7&gN1o+a!5@ESs!;gKq}a|Qy*jVIKI1UXp8On;T^!`a zsRn}O!0!6>1+nIZs8ZfS)7*+H<-6E4oI%wzN4@DwlrF| zK}l*Xu03h9x2h(cMy3LPn?@!{bDD-QD`FzTyT$Dj+^gIGCxEMaVAjc9VE9Vr12dgS z7@1_)B3NuS{uE^C<`Cmgt4;yAb=N`Ci^2xOMt8@}jp3dP$fKD~Fdft4B_ON)VOxPt ze~QlIpsF zQMVXiE2$ON!A5HqD?FfXo5@%pbq{=pjqcuekcWpJP#V*9Agjl|gRJU0kf(1x9HObF z8zmt*%7urR%P`%b#ML&B2V*o`Cy9xShXrCk{i$V6wOHXbHpitu~OJ* z#bTwf(LAGI9P2ZG3Q_Dq2+B%-)M5`WlT2zCZ{DQc+w_}N zV?$}bPrILg`4uIX3sMsKkQFs~|K;v3eN2~^ugGi36ZD{*wB(Llj>NXb-?3 z<7J+`c#gdN<9Uv}c;uBh7j(oIHtL`9(?*RtGNHs@lh-nGK`R}_l0Jm5h8=7T#xzoRhkLnj5&DH8Pj1TJ1HQR);#A_-jUvSba8%ipwU-&Ay)%eCn^$U;o z)cS^v4eHN$L3`@)k_yTf9L)(0Do)?3M|T<|VRz7N#)cY+>K7jE#twC1d{Dpe=r^kI zB8lo3zEGYVuac;KokUf$-K3)UsQ&3(-2U%>DEcx!s9$*I|DOK7g%9e#I;OV`N0z95 z9lR%sR^q{l>Yr{6ID*9CA@$P@0|nmVNx50yaQ-OaeIh}{whe0y>KC4HqKFrGQ2uoL zLcMP2^iln~eNCJvs)X@T{leSlhW~<5y;V{{5Tlm>W`f&s`57O*1f20<`N9V;0Sg~c zl`nko60q=5`N9V;0Sh0MFMRA4u;@Ycf(I`FiyoCPeDD&m@Ehb6Uo@Iof@xf5!_l?j z=vw3asDANF#o1Nj{HXrS7ah5Ootb|F1Z4!cm(lkG69F`rAqNF11T{G{IhRq%1{QzW zjvP61@ADP?*n-hCkKpBL2~err2K;Eug8}a@U<@ShjG*xx!tC!mf>)AECYdS84??T5 zl4LL#_rc;1|MS2f{_Q)S{@#B0?w? zBG%(h!?!Z-$)po8KF(uJo`ZI;Z2klZCr9Ul@4Giopu$>ZWOp{S-=2hwV$%A&y$q&1 z0j6~DTpwSL5PC!9g%)}Vpe2LqM^K4*7B9=~fh)nNIh$Fr+B94Q>N@fsrhvT%l zjtAmX;(<6rS<-FqMM^IlxMzP}$nVm7kt+&R2@(x)CXh8`898xFutSPIk=q+Na3NJ@0B5w1tiV)0`im33nQW459?QD;7`7SJ!)p&l}TPA6Kp&4jbboO?T z{Q$vnO$4?ZVP4(@v6_E1YG6-WpI0aGkH}qU!@!DW{>MLGN&EQYblbvsCcNA2L=YV$ zglAz?85?tEMNAskgOY~W2gAHoPPfd8?B)^q#I)v=N|(an5vv~Xin^vSDqzCs7RL8; z7?op=!zCEOpcL7idD0NIo{9Ec;!IheJ(B%&BOajvF-GT<(wD%_!aAUoB19 z!);0F-3a+M+nGti+>5}R?N4aMM7RFq=LJb~)G)pWpp{igaAuLG6Z4u{vSr1-W5gm# zw=IQ#Nshs-mwreF7aPZ4=kg8pt`TO0m3E&hlA<>GTNe+jCe^U(`ftHiZ=r1fxccVMTwOGo5P=P!^TTP@rmbF0`s$_`n3W4bN(79F=rlXXKRh&@`k) zv@L%cAQmJp93n%>9`3V(`astn2x~k5=~WBf8DWhM8@l@KxD#$3YIbN(WF@RoWg2dF z3$27Ty5p|LVA8j^6e3wLugPQ>$QJaDTrux6%Nw+?kq&}Hd^zM!71QHWoabdo`03>L z|Hu2!zyI|9&-YVY2z0`nlkLbQ(nWArOgoouOa=~rrN!g>-{*uunF)iOd=W;p-=N>w zkMo7lc(X*g-9lnX9K?}eZ8NgcA*kq69##5m@?_Tq_@?cnBbJiE9u5ixvf8b6N*(%- zBex`6oiMH?q08V%Rpn_&=G$cSk>d)f>dy-us#)0tpJ}nFhbnAbQhnOJSF3a z*D)W%+giLq6l=GU0~4{Ve@T*LcvQB>^OKr7+e(7diTixW#xw2Q8I_A%=8SDeyngkh zvOfKvzi9Lh9-`vb4reSVw+W>u)CXjZArpd-h`GHJySJAcmCb0);;kJdXdyF91N zZ9OR3O#m9B^LU_`MxpwFo8)rjl`F2=;2--5EiaPj;8VGV^ zaJ6Q}6(>o}gl>UYguR6#=G(#DR)*}6TuMY@g7hd%3+N)*VX2-|D++b;xux~qO9=4o z3P$71AU8!OiQ;4)!HNMQU)v)x`PuVsoL6W*5z@>%&=}c1vIlHwAY=zIq)!^p1 z8r<&cxXrEt+^m9~5r%z{_;~VfWa?9b+e_PEZ&9&H?GKVn{TAWDtB#^pd7Mb)teOUtMGQ%Op=qESaj9uwPz2NmueMEoaml|_ zDCKmNR|xIe`H0V3uOF`7^h7D$_RfH&+}IF*^K&m5d$)49Kdd&RmMp%XLk5G?TM!H!oy~TQO(~jHXzagiM9W<0$^r+d~qCAfZ!G#+W?@=^glECSi zXHkEir(CFb8`AEFa8;`2E$0jUa7d8n_=nE!tu!)@F8Foiwxt zyY!yoiCVG7Mg&BhzscA0vPZyW`S=01O}WXiRtxzW}z0Rh~gxI%IS$+XdD5)c%u z@kX?(%o7md&(Bl&No7`&s}_(?3)Tll26=m+6hy!`3H9bph)HgAr^Zp8>2AGdl5D(s zxATgB&51Z$z*6f*&vuH+x=*EjJP%H9GvWl&=XqlxsKHG(v-af$QmzUY!W*?`Sek#P zI}L8ie1jEUS}&#)eeikZ0cd904Vc^?95^Pc)vZ7)dDnzqkb-}Z8BocrAtcFFvn8s=S+CIn-K$94dP zqpj*47^nL~*D@DP7SXM+KxQym@T-3jG7l^Oz?~boNaj?Bs#JRhD|MiO0f+`PF$Yak z5BmiE-j2{WtH#CbMd9Hzt2|5Qd$o zs+U0dXxr>npR` zg(~WvE0-kLUfqT#yCg(S7ssQf$)^GoRoc5RsI;fL0V!MTFG}sno3cBKKUotkJvvrk z`l4v%OHuSJ52b7PjV zDo^Ps^QjiB@kuSpn{&#|X90rJ8&rCxNnt1G)**J#C|^x` zJ|E_Egc8}J^V=N^RHc7pP${3>KwyTo@Z@!QI8`nKd|7;Nw*ItDAci_O3jGBx%Mqy< z9`=Lc5Gd8ci_{Pr5=7bC4i@H{L@CQ{v**WuTKc5i%Vxxfg-ePamTIB;3zslo#?T!R z&6wZjtDw^*yPd38acBm~b~C@sm!S)UOurevs7*qNBis;WM|FSl0-d#v5+gaa_H1>T zU=ZrHpovck58SINX62_%q$w^KsQZM;3(7F1dy;t4GMl8IlKJ`Df{D>a(mnh2R~*zce%xp3DV>VeGB0k4dbq`*>1>fnrd0 z5QEC+o9xl__AY-)3w0fO2};+OOhTPwZv39z)k$Hp4Mnc=!1iIX)`m|Ts=BG#rUkzD z(MlC8)Osu~J->fdQWdN8b)@7F1>8RmwjS@8<Sn6 zm@DyTJCx1Uk`gwg{w|;_+(6Rqej&=~0un7`J7gIuRe2ze2JY&`|=$+Vf!>ycB?j7HqCcb5U?@r@Fodp{~8^FMAkV zA$%ma5VzJea1^<9R5xLmHM$2qtCHfCy1x5;>)gnu@`*b_>7i@E`>?q1(??0%g15i! z_5i!{J0CT3L?AUdi%UQ_-O;=U=Ujw`ntFs4y9j@e+uGi9eWTU8)|uP_Tzh))X_L;j zI#XWw-_|fcC{wfgT;X->E%s+3MpO@L?N+EIa%COeS>h|-$=Fjk!NfUW6$DVkSQqzi^ipdfq? zl~I3~GfVQNJ`p08`0lr=!6z@xwL4o?&p90wNr#NG73iDPBEXXl;&}#(BOme1|yi!s$Jzo(Et4+85IgH8#sPhCZk*r$C9S0*g$gAA7iDu zdU1g!kdt4MQ+`t6-hg4f%l+W0nJ{AC+pvEHa&++htk?oM1c81>-wca53Jl$Eb!W<$N>&rQ0_xa+C7$bJ6-!4_0F{U8|A&-2HBAGOdcDG`&l&_nj>Nx`<*R>x z=Xq^`{)pGMU1Y7w(0C#Prx~>pK&r}M!%1AX>S~O{Ua$w|D zEO}sxWYz^Nd57ToLo6NGvhOO&^(aGJXf>bl|lODW!z>vPPx2zYw)=w8G4 zZMl=-9_Nae)0p8eSiEfMhY?6UbAf-%)9LO?)%5;xX>@v{>q_YPJN!OHYeUU0nYey8 z`|MXm1pR`6wY6a%QgF)G)1GoOX_OnK>e5_okgj-&`Nx9P?m`~r2Yy3*+B9M2`JW{4 z)!i)0T{9Nbh?2ZiwV4{%+q(q~Ov+cGO#8OET4k`(m#8#qJJ8KhF0Ob6axYHsD-p_n zPqnjvrF$oL1hYSg1CyesyYSOL@=O*>x-a=m%v&Ervf}UmuXuDJOL+{rdtL+0e6?> zTLwQ)yyZ715vqO3TwJC^tn}_?H0{4ZIc>NY1e!B={ACfAQ_TAQ)XMb?dijIH5$lI{ zN$G(|?pxbKJT#O7GRLYU!MN>%DD}k zt2g*3KfG5);}eO$ajx&2%eVA@%ei>7_zu4^uYd6gw|D%iJb|7xw!5V^#(#Kkcz`$J zMlG>_b4xA7r!-b<1HEaV|9?;I<9j|CPrAcs)HgnM6}dHDlshu-8P#mRgnW<~6Ms>5c!=-0FOFrkC~~ z{(tn{?+#mP6_YN|mdaahbi;oiq<KEq~{$q+!nXJw5-P=BuVnlwwv7OZ-o6_{(x2 z<(Lt^Z}lTJ(KEs*t(Xqj#4;a}e0Y}YxoHOv-C=HGO-^H&FbA&f1WMti?uf^y-2pw} zx)TwGA}Oy&JPE;qF~ZG6q%ur7OEW|9Wk5Jt^Wi-V%!@=rxsj$9&w8kGAssWAj(;=5 zfy6IS(&3bxE>cK|B!yOlquB}AJx`Owu+kdB3*7|8HsS;~}U`o;yI56rYjoMAwtdl@1W}Qc$ z7oolsDMB*s%#zEy^e@Fe>Hb4G_zcEb6=|oEdoQS zD}Zyny|VKfR%@j{@-ppLh61>^-CAhLal;!@;NE~l@KH$umeK}EVf_a$Uwd* zU@pzqq5>I0R(9^F?BK1ZJ@s)S?^P6#iPMP>Nd!ykt`*|xNz2Z8$Y0N^(re~X$u}g} zFslrPc`HV$8H3QS0VDq~g)x{Xv_dTVlcH zoK{|)F!$^Lg7#$G6-B+@abUrK;;6RU?6-iO^HOy!w%AZ`2a3HP=7;q#un(Mf3wr*S zwc?bZ*sbqc>~u7+uCiT=i#i$}nlK&eWI3RtowOs>#742(s6zTpMSrGpB1-7DD$QGQ z2x_5`Zb`tdWfy234|=xWp7%-={C*<90JIJyzs7YEK#m>;T(g}tnkger*)Gf*c_s&{ zuZ4`XoQ2SH_gcnC8yGhau!3}gdEp*o1?dnO%Trdch}zz=o8q1{KH>na$wdJuZnX?0 zH87}t;Pfczz<867pMM^uJriP1vUBr|2Q%k0V0YPKjlB8-REqP4zN~6Lp^bc8M5Fq% zPL2H)w-C8WsGlgeGu&0#fuiJ~k>^s{i%5ZD)mLkdjL(d*vT;d%tF7%9zy3OB%mvFa z`5^4pPlDXhEOmz@I4Duj)?JhB8Anfvb$z4t8CRf;G$`w?$$$EgE5zhMpNukJjR4tW z1Mx}3k)W4>oKUgHB9^9nV+5#0*ODSSu!DSv zFQ`RlUB@RQ(v4>3eIa;)XnhU2*I91|TRpby1zzLIz7;879Qdd+flSy+R+}n~)M|$0 z&l{;y$=vb@6VJoe@7-)sev?I& zB^$<8xvx~`wUUw<2x9@LxBeUsn5z#;I@Vr}YxA#aTB zTYmHMUReA5ulU2IALX}i(vKhZCZWV0*&Aiyd^^_uIPheCo-@JS!<(~Sf`++E z^nY7iUxOB$8E1}bc-c9>M?U^>J&xq){2qtdx!rsWRF0>;6F6%xy#YG=fe+SZiZ&kj zKtDV)natvN_au)%{qkZt4BQW9t&N1kx^ z9<z&vUMl7jaqm?tWX^g#Kc>7}+xIoWFU!j?jyE}rL<$v*1 zpc1@%geSE&Ahi8CPtFI@fe9ra*+p$Eb51_SE!v4F1|As)&ZYF?L2l7-G-Vi>WrCTf zVh0*)r+SCmb!K`1cpA|8MvF4iTSe)u;RP_JV9?9B(=e;X0U8Eh${S;tAEviKasu#< z3Wot7!flG%YULFZyrjmE;Y3~i3V$Fc0WlkZ8r{NvUS=IhkH8lMsl`l-9BAKQWsvY( zx_*?ehGXbe1jOG@aMvd17}*9I7RdQ6bnNz097)rGr$DOiiPV;p#wxjX1+NvwsrfMoKhk z(6UG67ibeZJDfZ6j>UH~;FP`@fm8ba3UDH+2|~m8OTK#{T+Dvxn(Tp-6o4Csfi}Pi zpoWG=U6T!P0-Ryw$sp>?#1CK{c1?ENhCyMB>lq7hn)qPNZ77uwgkE!-Ks!R(1EDvO zWH2SrXVJErK&_MP*ax)Zw}0Qg``-phnwZvU6d+fS(SQE(?vHyaf8?&D?1<`m2`FTnQ33aNYH|i+_B3&g?LWUFaLM zq5~{8A7ySS1khi`_Dyye69aY@^+nt0$Cvj~2Dj528Z4k-9vsj37z-c9OHI~Wh*q)n zeh>dHY@xxpX4~Oz2hn+`h9K z^jg8W_2H01uS*WS{#Yq`$h2@~uuoM6sSGi%1vQ-i3s8)6*0%8#7yTPvT8c6u3s=U@Y;bX{O1*Nt z?7iv|x{1+GW6{!fp;)&mKr>NL$%;Pl}vz-K}`7l`;+^D2Mtg9l#BAF}akgPB- zhCL);v43Gom&}&4hyY?IJNB4L7{n}V>x8q=+bIwI5OH8HjYt9_|7=r*8b8@tZKh)I z@nM!NXEn2J6h+`GjtTPDZs@hmY<#Kn4b|31E&k8jP-0pqnW=e85M;VqrK1%h1TM zvd*E)qI;t+i`Gx=2BemrB2v?^GW!vcTFx?ZdY*2W+nj1#`!LA1<}r<%TXZ-ht+iA_ z;uG5-53*yeTBjBq5~hr!I1Ob;@r4XQRrwoIxaMm zbAPuMb(Ob$;YfZ;yI3%$3suDB-%by#Td7s${4sIhJRw&w9(r0`OaulX;DjBiT=M(U zEH3g{J{G>n0>6#4=lFCt!y9?{g>9A&g^tQ>?vO6^?U9wOA&-G9iS4FJ87 zMJOI-_%uPd_^6rW^QWJ_eEEKT{;)#8!j84gw#QE@IJ8o9jn-Q! zwS!~s;3uy^T)wF>=S<=D_kS}JFKD?v|8`S2j-^?uC&s3v+cClIu*WfVm5Ukdje9$R zz4=WOHhEl;#l64IDP{ntmBVSShkNb3C54=L^j3@2o2<3j8NlRXV_J_V!M@JI;-p<$ z`J}bU6QL67D(mQN3rW(GOD0!tJQ&OAX=_O2C#@lo9#tvXSF8Kixqs$P>(K|xf%+TW zjp^Gifk(En+IF%Bhhp1hOUjc$-s%7+yC^^yhtLK+s3g6;jEIm=wEkRl&Wco7Tx^zh z&n1D_65Mueyr-)rw$kzP82ET_GVgIxiQd z4q_NbOu{(&W4Q}1hksfzu`oIDs`b#Qa%Z;%s1i%`b*<{6O9k$Ae~NeHD!8BLCmdXn z3I1kRqzq?nQN&JO%+jOtJr6ShO7}VZdI6gHzGex~*P|5EjSq8rg-d=Ki)Lh3Chltu zXt{1QOBTX?scl;_e8};$jdM%O3+Rg$l823sg17Oyjn?g&Cx6k&!c#yZY? z&8NviYkqAgt-({*ZQXNs$LC2xgfUE6-;H_A$tZ$jQjC*D2KLFdu<_QK!!FT6XLo(Y zef4Tkr=?KJ>xSQno9mnD)wX`^eYKtm06-mKE?tKZv!wlT8{?W~$*SnVt@h)!wYpq_ zFj~Qd>B<-9g@4yzT(Q7KdkrY5f%CfcHODB&IJ|0mz5<2?5L8>+x7!<|PBMjlrMA@? z4hxSNIt~Vu@%qaPa9DW7M39HMZH(8zV?E$V!7puoYBM`c zogD8$18b+80i3t!iZTy$ysqsi1pS( zFFpNSkL=dcE-)|qSzS{DT43_YaVGN!*orb5%vgmIx9{nY2yy0~aLiqy$aqVNu6#3N zS0FSOYJcwrM=wY?x#6lk(RAfT`Wm)H<_slx;uoj5163+C(FU#g3_z)HxQyT{MoeQ2 zA(H~(RC{k@9_OtZB@xD{F>E)PVH)K;1lNZ3XPYHJHJRp2O?+-e_R6pHxe4u=RHhqr zrK?0=x-RFTNTjo(r~bnDROf_BY>(LKpF zx}F+tJHC);rznY>@&F)EktmGFhshk$9?3E!urw|De3R}=B-vp%r^xM6}9 zsWUpL+sk4iCHQ!f6jwXt$>n1{P~k-^_G;&L$q9-#TT9iq+j~I;9u?QO+PFcbj`za| zj(=7C{*oJ1IzTSrFgLL-B~e)7F;K#8Ji(JD8#k+l+GdF%MAE7l}YRKM?)EPn0m5TxgaYt^`Vom@xW+WyXuosQTHrxM+1S<0=R}-Ttt)K93$A8qD5I?!;w^Xv)f4uS?Vl>uRafnT|(bw^Q zIeTwP3+wG~vRPWT!@Clnn1NOAvn#1#ZHC@PM*!~z9@^zS|6#2n1XgybfgtsYJ+V#p zkY~B3wQ&)WZS7BxvmCP2hSx;(GoQxp0u2{HaCTg=i|Ki=ExdSgp7~4YLI<7xo@_!# zx&d*IjE8?%q;pQSH7E6NFHj|v{*-e)&=N7HMOO1ab#vuLXKAA8Qm3`y7mUhb0e80! zJ*nrqhN$|SgaJ{l(GV7hns(wlECi+v-r&?u{6wPQowOFS4J`A#N(n?AAICE0{|C+SoL!<2~Nu(&gNm;)A`%S+6^^2VT-+zAj{i*C*6w!e*Z$JO_MWq+= zO}#}gK$$o1tpJ_g{O9fOHz_~-`#*pFt<9&wN~RTzn@4LUr8iQl4=K%EN}E1^n~_jkx6^^@l0rx|Ge!`1R%_!djcA1d-q58M4mUA7R2uXa)1Bm@OGHweofhblT=E zng$ZW)8$i_#B>Irf2hJP->oD5t6bK|U%w;c z)bVWv_e8S753Uy-%&?n9C7rD~A;&p|I`#03Yq~4x$fUTHh}J64RbHimi&|K%i3TbQ zXvRBXmVoE;x6dv_#P?NrzH4t0U9A|piBxCGmLMnlrnKjfk+Gn%=xE1A4MzyzXc9V9 zyL}|ddKH~ee^gNx)q=KDc$Qq(mi3`)4=8kQSOLc|&27T?ZY|TcO>CJJ1E&~|;k=|E zm68KPppvo;2!#ACfk*^^NKa>DUeSOq!z9yPkO+n51<9@nGD(khnywBWZI8C**=kI0 zY$VMkyQ%{8v(B<=Z(XxDL;_PAZ3HQ)<{e0)WYy_Se~I9CLbTAmtkTsoQ-**Vp1w|_(qFkt#dD1 zABh@)lyCL0iSN4(lQ_2=<)czIycZjb7LyD$6b+G{{*jrIj76xhiN-kI?Op7dL97x0 zO&N6MBb$Yl>`LXk`h@J_z|RvObBCeXPjnHQ8*qBkD!K2@>KVU3mjrhPo_`;Nee)i6 z&e@qr7%)O>yBxruED|PK;g@4(Jh|fu$f2|2gUMqj^N^)S7o{|ivl?yx=$d8;s@xdI zn0sZ<2fjCOG?yTrMM2~!dU6ztfX*|xcoZfHp0j0va_Usntpl@{4ZT4u%EHaaKl*ly zpY3lmHJkH{7#*j1cE_etK!5Fez;&1b+PKQyVIT-cK8TH8BqP+k{2t zr9xM^XqEEBz?K3-oOhJfLePz`HxMk#JJN}hO)in+o#s)Rgz+mPk)37N790ErT>jY+ zEPUJONM_ePIz4A6seg`sOy*wNMw-pWb`qe1@GzwzD@cVCDK%5Gu~W{KXV=_=E7g}I z`o#o;Ngi|n-6a9lsD&ZH(1}b2kCF=jJhk7n@(Z$HJS2tRylE?$|LnqTbU-;^aB)s3 zP0;HCJs&Wds_u4-xr#WX;=-+)tT~0(;wPL_T@0S*fM<6(NPmjP#9x?mqiii?bkd5m z?+MNyl852ib{`q*65K|{XV(sMMyEl@T3POxJc(jb^T3NBJ}{{0}OW>y5FPD4};YNu;eybWo)&zpPY zZ?h-Q3SrIE6D$X-o7Ig8;W`&iwBl!9+_hoFQjU1=u$$5D(K&q^O_Uw}K1_259DmR^VhPi1YUkCS^2fJ3b&^LX z32vv2n2@xQhR6AtpUklq;nlP1yu%nQyoV9l8D6|yg57GI`5kw^NIFgx{Q zGI!Q$T<6Z+5hriLL0sePnh}a4cGXapim{oFq2Lkc-Qd{SM)F`5=kWXq9codZddEan z$!n;d0)Htz7)txiPDlR&TOuCgoI$lc_>TIHSBpw(4OVzq@6?h{3XD<%l}>toQvK-N z;YueQ50((l_60-qg^UZfglWCHjfl)4^Eczq?br*o;Rj~Nq#dzr6u zx4Pp@&FPRlYSV%z%RH9>HM_}ar>A}nlX^`Ex_=Tjv}Nn(4O;)1!?A8ii;u-vT#I?E zi;~2h*y=t}qGrX6aaD5lVOytgCa3Bq@@aow-0(^ylQK=>$+Xs&Vuu8i^|#~Fbuq?R z=Bi%X(Yf$~LSJ)ZY<7&|o$$4rXUWW~%h&;XDkhUu%MzD%gEH-E5KUI0!F6Jf-jH|u z9Di04X~|Jmr}UC*zurX>TNes1?*ng|+H;3iLOM4St+9vE`&m|46NXt|fBW`5hOg?p zeab`uPS4tt2wvQFeKQz^7mtzVUYEwQbOk+E#+rc%1Q91Ce)WF0;arjagYEm0jS3061$9D_AX(;2Sy6wF!= zYXX&Q)U(-rFoKCemO2Xw6>tMz#`5583>5pi%z`TQiR0bD8yh`Yki~lDaL40*41Z&P z>NCLgua5JmEOg*X7%5_}jnyhT7HQ#fiW|syP*lf)a)!Z6*oNQV;Kr`u$bSmfu{Q_yeekxV`h*=%Ar5qZ7PbiyNM|i$&vs4xRZy-s z80NG>+3?aKOcs`F*P{dkJb9gsRoEv;bgDFJO|py~%jQ028_etvEiicj19!313h$iX zPCcNb_>V~LyilQ$JU6BEb9*ldJmj|$9J}{uZ)f7gz#fR0Hv*!Y;eV?8dB0!A)~(oX zlmMnBenAOeVyA z`S+O@`8R{^ zrH!ZnzSM5&g-bfD^|LuQ9<@@rLeQ&jFtxDr`e1JcYph&?zyph9hMQ-+0UCQ=czPp| zR6SiKsno;OsT~5$oR_uEZ&%QoV_%IqlTfLDT|yyxVG~nNlz+I82rZ+~cAhl$?3l_f z?TSofecuN+J*^gQTKDV!YU0tveHL5^XGZ+L{v&w=-_G>8PG&0ot-EIW{OB@j&I?W` z{^cB4@WM%$ft3rtO<+#bvdQxm7M4v~+T#lp*XdJ53tDuY#X zY1%5rBxEv%i_ko4ZRe)frDLdF6{ULsAKUx)^|HQ7Qh#Z}i+A$Xr&Trqor-1INU}$q(G=oF0uds_k zzpWqCkZwVO%YJRHC2rKV=UUlM9d*le4699L>Bf3aCt~xkV4EEMWFy63J@tGQt>sCM zl84Q<9jQNKldI)l)qmq?e)9=D{eB3w+u@UoVt@Q{Z6L7gl|FC-R+l^O6+88BjVYZD z(+>2-&A{Y{2Jh!ty*?jq=b0uPv347T<%cNFe#@n9{Uu%7)}p)4zeF};o$%5hl5Ovd zCtWU794002QOZ-rW4sp9EP9Tm*5E~pOLi4Yd5^;?bZ!WY32V<}{A zFt2wkjUF@&v*UBo#`d0mN@mZVd477Ix8)WO`iKDS6&0j2mtgVkxy7++c|Hhwivi`(t!Eghor{Rk+@tjOIb=!(7e~E(U9Vjl?dvp|t4V9}kPhXYpjDmY z0T^zF?L>|SVHKj2k%~6jU^Ii}c>Kpc;w&<6kE6-{j1g;GNVqDA7JRS<33M+>MNrEv2m8R0#i>=VuATU3J^tNk|*GuOuPOUaHAD4Z_ZG`KiZKMy%k|IBMG%c z{wkgDm}RfctTkrlx!XT^+_ff_;uufJ6Y9MZZ;MroyF$>wM*=;PT}-E|z;x-0z31f= zG!4l$S?Y)q;2_L5U5~+HW9nryp@Y|Dg%es4m+f?tq);=}Qcv!+aECnUHF#E4E@Xhh z4qt+k%B`7Lp`}Zu=o1+W#@z}$Qf5x zVFO@nt$>DNdKx+IZa_TothitG1LP?7jr{_O5VnM4<`xw1csC$C0_lvYOC6^e%6a}o<;(2Z8KxD(IYU+3G~-!8ODHyCO~-!I{U}zI_xP&7KYEB?tF)Y<@YyQO@$->ok`t z*)TY>l`q7QVp-pP8i~-(<}QFWlrX2(YcgoaYu%(H52o!lVJ2FW=tYk0tKqj`i`XAS zP>cg*qsy22ETO{Y&0azXZAZ@%igtf*Vo-Z)1j%ukFv(4Ewq%4w6Q^Dwr5xGlZPvo` zk@XcRthLt7}C#{~;C6DHrQ}T>g^cLagrnM{}WUA1Wou*M;WyS-Zu>uXdJeF?=oN zKSiHO9A}73jx3x6WXnEa)gf@ri7crD3exvwt|0hx|KKu41p+JIgEs5E<;tk50bgE zIF89fi!piPa2F)PmrE6$36@?QRa3a~g)|AhJ%7EYL5&Z@VrC2u!`c+&szl#=5KZur zw_Kg%k-MzSQ<0mwl{ko80k+EUVxsW}!4M`218|+Ptb5O&Vn`tTzrmt%KhFP$ieULs zivExKRO<8=I1w-h$A6`#1~qi-v{?~-u4`_Hd3OE{8^uPKOVA<;07J#|{Zhqi8ZD~C za_u(_gznB^?mBm6@07%;x70&^ziQpzPrvnk@q9AQy1fY8t^8h1D*Pt?s)c8u)`c*n zP?2CuqApHDL=~P2lHs}u3G@m8!bAsCW{5|XvCdbqX9-s!z$;M!Fd7c1$*?6*6{lUO z>f4i%A7XS+(g`~fDCY+VGi-5+QbS-+Ls#k?;@_BU2p~pDp@j^FQCI6Hx!7cbgE0px zk3^BC4S_NCVeRv&EVLjEVeQNPo)>{Ot&A5Ttw09Dx)Xero?|CMJpz?xYLY$xUJAo2 zD6|q`B2X3YRj8B(h_NL(;)+sao>5>@NvZ`31=Mhd`t1~SMdAn0kFkKEgb^?KQGuZO zu#5gnQfvFY5FMyd`nE^%yX^HrG3bof6**t!?1gsm5RAyt1?hqWl~5=5x9ehxI|zJ! zl8BB#aBU9+$1+kDbs4TYsBhjCD9!PioC5tZED;w4Lk$E5fKI9Qm%^-Sm6<=jssV$E zirXM_X#C0DYG#@kj&Jf=wt^l_A+<5vXt*tF#dY*_ge2i83WBv#&GVo^E;^;3c!~9+ zVpJQof?OGv-VTiIgXg`>4|N*v0xfUy4oQU3w!2@qoiAkD z5a&B6n|JtO2u14GZ&hfHjeJj971-Mck3Pz3jmBCxoHyIBca55vIeGiJ zdj4ETs`aMRjj>heRiE+IKKQ)Xe8;;NbN}g3{&Pd(s}_i?O399NpMP!YRq}MlW`V0+ z5Ay);2FxXC;r)lq=1e>uox5( zUVBS^AmIfvO{Kh#wLNtQ6YhB~ia0yw&*)OZpZ18LSl&DC;%LY-$eKZocSY*Cg<1+c zh2$ny1+Zi{7@|s~=)?lz6N64JZcH|XlM6seP3+{w;En6O?kxRRD~^g<4aDNEBQp)V zn&!4m@F$OURrRu2|DyW+q8UH@apdd$qL#!0?l3ZK9>v53Eo63iBkO?qYV=Lyhj4(3MKFQ*nfVLnvgBR86gm=6$N4dBh&H;=dlxk_NM4&!O;ipLWkWCBTRE z%eiNlMrF!V`s3dU(`S|!NVqXN1p6$FPNjkOVn(CXkkr0HD5S?01 zbB&xHXi{!D3s=o7GZpGP2UZaHHZnj~ujgf%f;?BFUi7+;b{|k{ob;dfQN)JDgiM7_ z#!B=74Y_9}&cg5+>wZDR2xP5GRZ21Jf1!!SP`&5Ap{vYF(T!^nU6G9*Jg6shd0(T* zM)-Kt+5ydk5B>2W3FFUwv$7hOu1c<@Peu6Cv&D0=5Gs{MXTieTGrZ4zAVPoxTC`CT z?E$XS)M_+N7dusuC?h^|;7v(RcE=;!GPKD$t5rD69*E~F@}>1Kw%Icmrdh(yMz=4w z{KN-?d=y{j{KWdq6Qxx$MhBZ2rN4~}1i!d>`C^7iAxD!)L z-`ci+`VX-dx=6%*i&IG<3X6A{!?v6W>#dSgkWAxkgoxBPw*_rDzuoG5?}xox-@K|P z(8ssc&iN6l+8AMkOt!Q-TLWM;QXe;3$L?Kyk0UF_4SZO$^k9!`LLUKylcy}OF|6IX zh{*XAghuDz_F9)r7IGQk0|@g80}w?;yf19iBK4Z)u6@J>O}Vxldlkv2re@G`V8;n3 z#KBvgzuNIV?V@YA2_MC3HxUkkIvZUfjyaSwPbM3zYER;tUmbwBjuAkdaOtt4IN(xAyT^Y-O8{LN;1EnEuRdP7B1IAc3~0DBvQdWoVjGcu7i~ zcF`yNC{kM&{lf@h?CXI7Z0^RaEOte{89@A?LL_|ZdR%8a-XjWOQQ-UjaOL)$rch;n z!p4S*Uk*SFM7530~)zL8I7Uwz;xQ23*r&(A8hVXvp^S-oY*&D7Si~Y{;Y)_-E(W7AI^Kc2D47X>)Dr!E^-}*f(tQ8U=H7rTLncxme-F2l5Gj4k! zp2T7B=PT-NDGDlX{d=4Il%wLFeRy4{qe0+KG1*hkcY?xc+g%%y2av1>dWAM-N^}os z%0A-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 Date: Thu, 28 Sep 2023 14:46:20 -0400 Subject: [PATCH 31/37] Fix transactions (#1825) * incorporate VID transaction commitments into hash * remove commitment calculation * fix number of transactions to send * split out function * generate transactions JIT --- crates/hotshot/examples/infra/modDA.rs | 92 ++++++++----------- crates/hotshot/src/demo.rs | 6 +- .../default-libp2p-run-config.toml | 2 +- 3 files changed, 45 insertions(+), 55 deletions(-) diff --git a/crates/hotshot/examples/infra/modDA.rs b/crates/hotshot/examples/infra/modDA.rs index 82cc12bf68..ef188a7849 100644 --- a/crates/hotshot/examples/infra/modDA.rs +++ b/crates/hotshot/examples/infra/modDA.rs @@ -47,6 +47,8 @@ use libp2p_networking::{ network::{MeshParams, NetworkNodeConfigBuilder, NetworkNodeType}, reexport::Multiaddr, }; +use rand::rngs::StdRng; +use rand::SeedableRng; use std::{collections::BTreeSet, sync::Arc}; use std::{num::NonZeroUsize, str::FromStr}; // use libp2p::{ @@ -59,9 +61,9 @@ use std::{num::NonZeroUsize, str::FromStr}; // }; use libp2p_identity::PeerId; // use libp2p_networking::network::{MeshParams, NetworkNodeConfigBuilder, NetworkNodeType}; +use std::{fmt::Debug, net::Ipv4Addr}; use std::{ //collections::{BTreeSet, VecDeque}, - collections::VecDeque, //fs, mem, net::IpAddr, @@ -71,7 +73,6 @@ use std::{ //time::{Duration, Instant}, time::Instant, }; -use std::{fmt::Debug, net::Ipv4Addr}; //use surf_disco::error::ClientError; //use surf_disco::Client; use tracing::{debug, error, info, warn}; @@ -125,6 +126,19 @@ pub async fn run_orchestrator_da< .await; } +/// Helper function to calculate the nuymber of transactions to send per node per round +fn calculate_num_tx_per_round( + node_index: u64, + total_num_nodes: usize, + transactions_per_round: usize, +) -> usize { + if node_index == 0 { + transactions_per_round / total_num_nodes + transactions_per_round % total_num_nodes + } else { + transactions_per_round / total_num_nodes + } +} + /// Defines the behavior of a "run" of the network with a given configuration #[async_trait] pub trait RunDA< @@ -254,38 +268,23 @@ pub trait RunDA< } = self.get_config(); let size = mem::size_of::(); - let adjusted_padding = if padding < size { 0 } else { padding - size }; - let mut txns: VecDeque = VecDeque::new(); - - // TODO ED: In the future we should have each node generate transactions every round to simulate a more realistic network - let tx_to_gen = transactions_per_round * rounds * 3; - { - let mut txn_rng = rand::thread_rng(); - for _ in 0..tx_to_gen { - let txn = - <::StateType as TestableState>::create_random_transaction( - None, - &mut txn_rng, - padding as u64, - ); - txns.push_back(txn); - } - } - debug!("Generated {} transactions", tx_to_gen); + let padding = padding.saturating_sub(size); + let mut txn_rng = StdRng::seed_from_u64(node_index); - debug!("Adjusted padding size is {:?} bytes", adjusted_padding); - let mut round = 0; - let mut total_transactions = 0; + debug!("Adjusted padding size is {:?} bytes", padding); - let start = Instant::now(); + let mut total_transactions_committed = 0; + let mut total_transactions_sent = 0; + let transactions_to_send_per_round = + calculate_num_tx_per_round(node_index, total_nodes.get(), transactions_per_round); info!("Starting hotshot!"); + let start = Instant::now(); + let (mut event_stream, _streamid) = context.get_event_stream(FilterEvent::default()).await; let mut anchor_view: TYPES::Time = ::genesis(); let mut num_successful_commits = 0; - let total_nodes_u64 = total_nodes.get() as u64; - context.hotshot.start_consensus().await; loop { @@ -314,8 +313,20 @@ pub trait RunDA< } } + // send transactions + for _ in 0..transactions_to_send_per_round { + let txn = + <::StateType as TestableState>::create_random_transaction( + None, + &mut txn_rng, + padding as u64, + ); + _ = context.submit_transaction(txn).await.unwrap(); + total_transactions_sent += 1; + } + if let Some(size) = block_size { - total_transactions += size; + total_transactions_committed += size; } num_successful_commits += leaf_chain.len(); @@ -334,39 +345,16 @@ pub trait RunDA< EventType::NextLeaderViewTimeout { view_number } => { warn!("Timed out as the next leader in view {:?}", view_number); } - EventType::ViewFinished { view_number } => { - if *view_number > round { - round = *view_number; - info!("view finished: {:?}", view_number); - for _ in 0..transactions_per_round { - if node_index >= total_nodes_u64 - 10 { - let txn = txns.pop_front().unwrap(); - - debug!("Submitting txn on round {}", round); - - let result = context.submit_transaction(txn).await; - - if result.is_err() { - error! ( - "Could not send transaction to web server on round {}", - round - ) - } - } - } - } - } + EventType::ViewFinished { view_number: _ } => {} _ => unimplemented!(), } } } - - round += 1; } // Output run results let total_time_elapsed = start.elapsed(); - error!("{rounds} rounds completed in {total_time_elapsed:?} - Total transactions committed: {total_transactions} - Total commitments: {num_successful_commits}"); + error!("[{node_index}]: {rounds} rounds completed in {total_time_elapsed:?} - Total transactions sent: {total_transactions_sent} - Total transactions committed: {total_transactions_committed} - Total commitments: {num_successful_commits}"); } /// Returns the da network for this run diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index 81cac76f4b..97509c3b21 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -100,12 +100,14 @@ impl State for SDemoState { impl TestableState for SDemoState { fn create_random_transaction( _state: Option<&Self>, - _rng: &mut dyn rand::RngCore, + rng: &mut dyn rand::RngCore, padding: u64, ) -> ::Transaction { /// clippy appeasement for `RANDOM_TX_BASE_SIZE` const RANDOM_TX_BASE_SIZE: usize = 8; - VIDTransaction(vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]) + let mut bytes = vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]; + rng.fill_bytes(&mut bytes); + VIDTransaction(bytes) } } /// Implementation of [`NodeType`] for [`VDemoNode`] diff --git a/crates/orchestrator/default-libp2p-run-config.toml b/crates/orchestrator/default-libp2p-run-config.toml index c217d24d1c..a353ed06f5 100644 --- a/crates/orchestrator/default-libp2p-run-config.toml +++ b/crates/orchestrator/default-libp2p-run-config.toml @@ -1,5 +1,5 @@ rounds = 10 -transactions_per_round = 10 +transactions_per_round = 12 node_index = 0 seed = [ 0, From 7c48e20293ed9dc57a1ce354ed0a37b4408a97f2 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:45:14 -0400 Subject: [PATCH 32/37] Speed up linting by moving it to the build workflow (#1832) --- .github/workflows/build.yml | 6 +++++- .github/workflows/lints.yml | 42 ------------------------------------- 2 files changed, 5 insertions(+), 43 deletions(-) delete mode 100644 .github/workflows/lints.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e7ac7ecdb4..151e8a8a50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build and Test Workflow +name: Build, Lint, and Test on: push: @@ -43,6 +43,10 @@ jobs: sudo apt-get install -y protobuf-compiler cargo install just + - name: Run linting + run: | + just ${{ matrix.just_variants }} lint + - name: Build all crates in workspace run: just ${{ matrix.just_variants }} build diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml deleted file mode 100644 index 61106f6d0c..0000000000 --- a/.github/workflows/lints.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Lints Workflow - -on: - push: - branches: - - 'main' - pull_request: - branches: - - 'main' - - '*/*' - workflow_dispatch: - -jobs: - lints: - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - uses: styfle/cancel-workflow-action@0.11.0 - name: Cancel Outdated Builds - with: - all_but_latest: true - access_token: ${{ github.token }} - - - name: Install Nix - uses: cachix/install-nix-action@v23 - - - uses: actions/checkout@v4 - name: Checkout Repository - - - uses: Swatinem/rust-cache@v2 - name: Enable Rust Caching - with: - shared-key: "" - prefix-key: lint - - - name: Format Check - run: cargo fmt -- --check - - - name: Clippy - run: | - nix develop -c just async_std lint - nix develop -c just tokio lint From 2a15fe544c3ebf2f9dca6e046b476d688e4a6ecd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 03:24:22 +0000 Subject: [PATCH 33/37] Bump clap from 4.4.5 to 4.4.6 Bumps [clap](https://github.com/clap-rs/clap) from 4.4.5 to 4.4.6. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.5...v4.4.6) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c1554b852..5f2c5e9a49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,9 +164,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "f6cd65a4b849ace0b7f6daeebcc1a1d111282227ca745458c61dbf670e52a597" dependencies = [ "anstyle", "anstyle-parse", @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "0238ca56c96dfa37bdf7c373c8886dd591322500aceeeccdb2216fe06dc2f796" dependencies = [ "anstyle", "windows-sys", @@ -1208,9 +1208,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.5" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", @@ -1218,9 +1218,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.5" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", From 67be089d961c9db9b34eb7677fc34fbabf174f00 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Fri, 29 Sep 2023 15:26:13 -0400 Subject: [PATCH 34/37] Fix/re-enable memory network tests (#1831) --- .../src/traits/networking/memory_network.rs | 356 ----------------- crates/testing/tests/memory_network.rs | 368 ++++++++++++++++++ 2 files changed, 368 insertions(+), 356 deletions(-) create mode 100644 crates/testing/tests/memory_network.rs diff --git a/crates/hotshot/src/traits/networking/memory_network.rs b/crates/hotshot/src/traits/networking/memory_network.rs index 51f7bbbdf7..976186c030 100644 --- a/crates/hotshot/src/traits/networking/memory_network.rs +++ b/crates/hotshot/src/traits/networking/memory_network.rs @@ -574,359 +574,3 @@ impl, MEMBERSHIP: Membership; - // type Transaction = VDemoTransaction; - // type ElectionConfigType = StaticElectionConfig; - // type StateType = VDemoState; - // } - // - // type TestMembership = GeneralStaticCommittee; - // type TestNetwork = MemoryCommChannel; - // - // impl NodeImplementation for TestImpl { - // type ConsensusMessage = ValidatingMessage; - // type Exchanges = ValidatingExchanges< - // Test, - // Message, - // QuorumExchange< - // Test, - // TestLeaf, - // TestProposal, - // TestMembership, - // TestNetwork, - // Message, - // >, - // ViewSyncExchange>, - // >; - // type Leaf = TestLeaf; - // type Storage = MemoryStorage; - // - // fn new_channel_maps( - // start_view: ViewNumber, - // ) -> (ChannelMaps, Option>) { - // (ChannelMaps::new(start_view), None) - // } - // } - // - // type TestLeaf = ValidatingLeaf; - // type TestVote = QuorumVote; - // type TestProposal = ValidatingProposal; - // - // /// fake Eq - // /// we can't compare the votetokentype for equality, so we can't - // /// derive EQ on `VoteType` and thereby message - // /// we are only sending data messages, though so we compare key and - // /// data message - // fn fake_message_eq(message_1: Message, message_2: Message) { - // assert_eq!(message_1.sender, message_2.sender); - // if let MessageKind::Data(DataMessage::SubmitTransaction(d_1, _)) = message_1.kind { - // if let MessageKind::Data(DataMessage::SubmitTransaction(d_2, _)) = message_2.kind { - // assert_eq!(d_1, d_2); - // } - // } else { - // panic!("Got unexpected message type in memory test!"); - // } - // } - // - // #[instrument] - // fn get_pubkey() -> Ed25519Pub { - // let priv_key = Ed25519Priv::generate(); - // Ed25519Pub::from_private(&priv_key) - // } - // - // /// create a message - // fn gen_messages(num_messages: u64, seed: u64, pk: Ed25519Pub) -> Vec> { - // let mut messages = Vec::new(); - // for i in 0..num_messages { - // let message = Message { - // sender: pk, - // kind: MessageKind::Data(DataMessage::SubmitTransaction( - // VDemoTransaction { - // add: Addition { - // account: "A".to_string(), - // amount: 50 + i + seed, - // }, - // sub: Subtraction { - // account: "B".to_string(), - // amount: 50 + i + seed, - // }, - // nonce: seed + i, - // padding: vec![50; 0], - // }, - // ::new(0), - // )), - // _phantom: PhantomData, - // }; - // messages.push(message); - // } - // messages - // } - // - // // Spawning a single MemoryNetwork should produce no errors - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[instrument] - // async fn spawn_single() { - // setup_logging(); - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key = get_pubkey(); - // let _network = MemoryNetwork::new(pub_key, NoMetrics::boxed(), group, Option::None); - // } - // - // // // Spawning a two MemoryNetworks and connecting them should produce no errors - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[instrument] - // async fn spawn_double() { - // setup_logging(); - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key_1 = get_pubkey(); - // let _network_1 = - // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // let pub_key_2 = get_pubkey(); - // let _network_2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // } - // - // // Check to make sure direct queue works - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[allow(deprecated)] - // #[instrument] - // async fn direct_queue() { - // setup_logging(); - // // Create some dummy messages - // - // // Make and connect the networking instances - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key_1 = get_pubkey(); - // let network1 = - // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // let pub_key_2 = get_pubkey(); - // let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // - // let first_messages: Vec> = gen_messages(5, 100, pub_key_1); - // - // // Test 1 -> 2 - // // Send messages - // for sent_message in first_messages { - // network1 - // .direct_message(sent_message.clone(), pub_key_2) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network2 - // .recv_msgs(TransmitType::Direct) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // - // let second_messages: Vec> = gen_messages(5, 200, pub_key_2); - // - // // Test 2 -> 1 - // // Send messages - // for sent_message in second_messages { - // network2 - // .direct_message(sent_message.clone(), pub_key_1) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network1 - // .recv_msgs(TransmitType::Direct) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // } - // - // // Check to make sure direct queue works - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[allow(deprecated)] - // #[instrument] - // async fn broadcast_queue() { - // setup_logging(); - // // Make and connect the networking instances - // let group: Arc, ::SignatureKey>> = - // MasterMap::new(); - // trace!(?group); - // let pub_key_1 = get_pubkey(); - // let network1 = - // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // let pub_key_2 = get_pubkey(); - // let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // - // let first_messages: Vec> = gen_messages(5, 100, pub_key_1); - // - // // Test 1 -> 2 - // // Send messages - // for sent_message in first_messages { - // network1 - // .broadcast_message( - // sent_message.clone(), - // vec![pub_key_2].into_iter().collect::>(), - // ) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network2 - // .recv_msgs(TransmitType::Broadcast) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // - // let second_messages: Vec> = gen_messages(5, 200, pub_key_2); - // - // // Test 2 -> 1 - // // Send messages - // for sent_message in second_messages { - // network2 - // .broadcast_message( - // sent_message.clone(), - // vec![pub_key_1].into_iter().collect::>(), - // ) - // .await - // .expect("Failed to message node"); - // let mut recv_messages = network1 - // .recv_msgs(TransmitType::Broadcast) - // .await - // .expect("Failed to receive message"); - // let recv_message = recv_messages.pop().unwrap(); - // assert!(recv_messages.is_empty()); - // fake_message_eq(sent_message, recv_message); - // } - // } - // - // #[cfg_attr( - // feature = "tokio-executor", - // tokio::test(flavor = "multi_thread", worker_threads = 2) - // )] - // #[cfg_attr(feature = "async-std-executor", async_std::test)] - // #[instrument] - // #[allow(deprecated)] - // async fn test_in_flight_message_count() { - // // setup_logging(); - // - // // let group: Arc, ::SignatureKey>> = - // // MasterMap::new(); - // // trace!(?group); - // // let pub_key_1 = get_pubkey(); - // // let network1 = - // // MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); - // // let pub_key_2 = get_pubkey(); - // // let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); - // - // // // Create some dummy messages - // // let messages: Vec> = gen_messages(5, 100, pub_key_1); - // - // // // assert_eq!(network1.in_flight_message_count(), Some(0)); - // // // assert_eq!(network2.in_flight_message_count(), Some(0)); - // - // // for (_count, message) in messages.iter().enumerate() { - // // network1 - // // .direct_message(message.clone(), pub_key_2) - // // .await - // // .unwrap(); - // // // network 2 has received `count` broadcast messages and `count + 1` direct messages - // // // assert_eq!(network2.in_flight_message_count(), Some(count + count + 1)); - // - // // // network2.broadcast_message(message.clone()).await.unwrap(); - // // // network 1 has received `count` broadcast messages - // // // assert_eq!(network1.in_flight_message_count(), Some(count + 1)); - // - // // // network 2 has received `count + 1` broadcast messages and `count + 1` direct messages - // // // assert_eq!(network2.in_flight_message_count(), Some((count + 1) * 2)); - // // } - // - // // for _count in (0..messages.len()).rev() { - // // network1.recv_msgs(TransmitType::Broadcast).await.unwrap(); - // // // assert_eq!(network1.in_flight_message_count(), Some(count)); - // - // // network2.recv_msgs(TransmitType::Broadcast).await.unwrap(); - // // network2.recv_msgs(TransmitType::Direct).await.unwrap(); - // // // assert_eq!(network2.in_flight_message_count(), Some(count * 2)); - // // } - // - // // // assert_eq!(network1.in_flight_message_count(), Some(0)); - // // // assert_eq!(network2.in_flight_message_count(), Some(0)); - // } -} diff --git a/crates/testing/tests/memory_network.rs b/crates/testing/tests/memory_network.rs new file mode 100644 index 0000000000..d1a231a2c0 --- /dev/null +++ b/crates/testing/tests/memory_network.rs @@ -0,0 +1,368 @@ +use std::collections::BTreeSet; +use std::marker::PhantomData; +use std::sync::Arc; + +use async_compatibility_layer::logging::setup_logging; +use hotshot::demo::SDemoState; +use hotshot::traits::election::static_committee::{ + GeneralStaticCommittee, StaticElectionConfig, StaticVoteToken, +}; +use hotshot::traits::implementations::{ + MasterMap, MemoryCommChannel, MemoryNetwork, MemoryStorage, +}; +use hotshot::traits::NodeImplementation; +use hotshot::types::bn254::{BLSPrivKey, BLSPubKey}; +use hotshot::types::SignatureKey; +use hotshot_types::block_impl::{VIDBlockPayload, VIDTransaction}; +use hotshot_types::certificate::ViewSyncCertificate; +use hotshot_types::data::{DAProposal, QuorumProposal, SequencingLeaf}; +use hotshot_types::message::{Message, SequencingMessage}; +use hotshot_types::traits::election::{CommitteeExchange, QuorumExchange, ViewSyncExchange}; +use hotshot_types::traits::metrics::NoMetrics; +use hotshot_types::traits::network::TestableNetworkingImplementation; +use hotshot_types::traits::network::{ConnectedNetwork, TransmitType}; +use hotshot_types::traits::node_implementation::{ChannelMaps, NodeType, SequencingExchanges}; +use hotshot_types::vote::{DAVote, ViewSyncVote}; +use hotshot_types::{ + data::ViewNumber, + message::{DataMessage, MessageKind}, + traits::state::ConsensusTime, + vote::QuorumVote, +}; +use rand::rngs::StdRng; +use rand::{RngCore, SeedableRng}; +use serde::{Deserialize, Serialize}; +use tracing::instrument; +use tracing::trace; + +#[derive( + Copy, + Clone, + Debug, + Default, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + serde::Serialize, + serde::Deserialize, +)] +pub struct Test; + +impl NodeType for Test { + type Time = ViewNumber; + type BlockType = VIDBlockPayload; + type SignatureKey = BLSPubKey; + type VoteTokenType = StaticVoteToken; + type Transaction = VIDTransaction; + type ElectionConfigType = StaticElectionConfig; + type StateType = SDemoState; +} + +#[derive(Clone, Debug, Deserialize, Serialize, Hash, PartialEq, Eq)] +pub struct TestImpl {} + +pub type ThisLeaf = SequencingLeaf; +pub type ThisMembership = GeneralStaticCommittee::SignatureKey>; +pub type DANetwork = MemoryCommChannel; +pub type QuorumNetwork = MemoryCommChannel; +pub type ViewSyncNetwork = MemoryCommChannel; + +pub type ThisDAProposal = DAProposal; +pub type ThisDAVote = DAVote; + +pub type ThisQuorumProposal = QuorumProposal; +pub type ThisQuorumVote = QuorumVote; + +pub type ThisViewSyncProposal = ViewSyncCertificate; +pub type ThisViewSyncVote = ViewSyncVote; + +impl NodeImplementation for TestImpl { + type Storage = MemoryStorage; + type Leaf = SequencingLeaf; + type Exchanges = SequencingExchanges< + Test, + Message, + QuorumExchange< + Test, + Self::Leaf, + ThisQuorumProposal, + ThisMembership, + QuorumNetwork, + Message, + >, + CommitteeExchange>, + ViewSyncExchange< + Test, + ThisViewSyncProposal, + ThisMembership, + ViewSyncNetwork, + Message, + >, + >; + type ConsensusMessage = SequencingMessage; + + fn new_channel_maps( + start_view: ::Time, + ) -> (ChannelMaps, Option>) { + (ChannelMaps::new(start_view), None) + } +} + +/// fake Eq +/// we can't compare the votetokentype for equality, so we can't +/// derive EQ on `VoteType` and thereby message +/// we are only sending data messages, though so we compare key and +/// data message +fn fake_message_eq(message_1: Message, message_2: Message) { + assert_eq!(message_1.sender, message_2.sender); + if let MessageKind::Data(DataMessage::SubmitTransaction(d_1, _)) = message_1.kind { + if let MessageKind::Data(DataMessage::SubmitTransaction(d_2, _)) = message_2.kind { + assert_eq!(d_1, d_2); + } + } else { + panic!("Got unexpected message type in memory test!"); + } +} + +#[instrument] +fn get_pubkey() -> BLSPubKey { + // random 32 bytes + let mut bytes = [0; 32]; + rand::thread_rng().fill_bytes(&mut bytes); + BLSPubKey::from_private(&BLSPrivKey::generate_from_seed(bytes)) +} + +/// create a message +fn gen_messages(num_messages: u64, seed: u64, pk: BLSPubKey) -> Vec> { + let mut messages = Vec::new(); + for _ in 0..num_messages { + // create a random transaction from seed + let mut bytes = [0u8; 8]; + let mut rng = StdRng::seed_from_u64(seed); + rng.fill_bytes(&mut bytes); + + let message = Message { + sender: pk, + kind: MessageKind::Data(DataMessage::SubmitTransaction( + VIDTransaction(bytes.to_vec()), + ::new(0), + )), + _phantom: PhantomData, + }; + messages.push(message); + } + messages +} + +// Spawning a single MemoryNetwork should produce no errors +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_spawn_single() { + setup_logging(); + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key = get_pubkey(); + let _network = MemoryNetwork::new(pub_key, NoMetrics::boxed(), group, Option::None); +} + +// // Spawning a two MemoryNetworks and connecting them should produce no errors +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_spawn_double() { + setup_logging(); + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key_1 = get_pubkey(); + let _network_1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + let pub_key_2 = get_pubkey(); + let _network_2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); +} + +// Check to make sure direct queue works +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_direct_queue() { + setup_logging(); + // Create some dummy messages + + // Make and connect the networking instances + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + + let pub_key_1 = get_pubkey(); + let network1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + + let pub_key_2 = get_pubkey(); + let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); + + let first_messages: Vec> = gen_messages(5, 100, pub_key_1); + + // Test 1 -> 2 + // Send messages + for sent_message in first_messages { + network1 + .direct_message(sent_message.clone(), pub_key_2) + .await + .expect("Failed to message node"); + let mut recv_messages = network2 + .recv_msgs(TransmitType::Direct) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } + + let second_messages: Vec> = gen_messages(5, 200, pub_key_2); + + // Test 2 -> 1 + // Send messages + for sent_message in second_messages { + network2 + .direct_message(sent_message.clone(), pub_key_1) + .await + .expect("Failed to message node"); + let mut recv_messages = network1 + .recv_msgs(TransmitType::Direct) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } +} + +// Check to make sure direct queue works +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +async fn memory_network_broadcast_queue() { + setup_logging(); + // Make and connect the networking instances + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key_1 = get_pubkey(); + let network1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + let pub_key_2 = get_pubkey(); + let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); + + let first_messages: Vec> = gen_messages(5, 100, pub_key_1); + + // Test 1 -> 2 + // Send messages + for sent_message in first_messages { + network1 + .broadcast_message( + sent_message.clone(), + vec![pub_key_2].into_iter().collect::>(), + ) + .await + .expect("Failed to message node"); + let mut recv_messages = network2 + .recv_msgs(TransmitType::Broadcast) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } + + let second_messages: Vec> = gen_messages(5, 200, pub_key_2); + + // Test 2 -> 1 + // Send messages + for sent_message in second_messages { + network2 + .broadcast_message( + sent_message.clone(), + vec![pub_key_1].into_iter().collect::>(), + ) + .await + .expect("Failed to message node"); + let mut recv_messages = network1 + .recv_msgs(TransmitType::Broadcast) + .await + .expect("Failed to receive message"); + let recv_message = recv_messages.pop().unwrap(); + assert!(recv_messages.is_empty()); + fake_message_eq(sent_message, recv_message); + } +} + +#[cfg_attr( + async_executor_impl = "tokio", + tokio::test(flavor = "multi_thread", worker_threads = 2) +)] +#[cfg_attr(async_executor_impl = "async-std", async_std::test)] +#[instrument] +#[allow(deprecated)] +async fn memory_network_test_in_flight_message_count() { + setup_logging(); + + let group: Arc, ::SignatureKey>> = + MasterMap::new(); + trace!(?group); + let pub_key_1 = get_pubkey(); + let network1 = MemoryNetwork::new(pub_key_1, NoMetrics::boxed(), group.clone(), Option::None); + let pub_key_2 = get_pubkey(); + let network2 = MemoryNetwork::new(pub_key_2, NoMetrics::boxed(), group, Option::None); + + // Create some dummy messages + let messages: Vec> = gen_messages(5, 100, pub_key_1); + let broadcast_recipients = BTreeSet::from([pub_key_1, pub_key_2]); + + assert_eq!(network1.in_flight_message_count(), Some(0)); + assert_eq!(network2.in_flight_message_count(), Some(0)); + + for (count, message) in messages.iter().enumerate() { + network1 + .direct_message(message.clone(), pub_key_2) + .await + .unwrap(); + // network 2 has received `count` broadcast messages and `count + 1` direct messages + assert_eq!(network2.in_flight_message_count(), Some(count + count + 1)); + + network2 + .broadcast_message(message.clone(), broadcast_recipients.clone()) + .await + .unwrap(); + // network 1 has received `count` broadcast messages + assert_eq!(network1.in_flight_message_count(), Some(count + 1)); + + // network 2 has received `count + 1` broadcast messages and `count + 1` direct messages + assert_eq!(network2.in_flight_message_count(), Some((count + 1) * 2)); + } + + while network1.in_flight_message_count().unwrap() > 0 { + network1.recv_msgs(TransmitType::Broadcast).await.unwrap(); + } + + while network2.in_flight_message_count().unwrap() > 0 { + network2.recv_msgs(TransmitType::Broadcast).await.unwrap(); + network2.recv_msgs(TransmitType::Direct).await.unwrap(); + } + + assert_eq!(network1.in_flight_message_count(), Some(0)); + assert_eq!(network2.in_flight_message_count(), Some(0)); +} From 27b0731d23850bfdf070c9fb3414fb44f62f8189 Mon Sep 17 00:00:00 2001 From: rob-maron <132852777+rob-maron@users.noreply.github.com> Date: Fri, 29 Sep 2023 15:51:50 -0400 Subject: [PATCH 35/37] fix: revert to using fixed val for transactions (#1835) --- crates/hotshot/src/demo.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/hotshot/src/demo.rs b/crates/hotshot/src/demo.rs index 97509c3b21..81cac76f4b 100644 --- a/crates/hotshot/src/demo.rs +++ b/crates/hotshot/src/demo.rs @@ -100,14 +100,12 @@ impl State for SDemoState { impl TestableState for SDemoState { fn create_random_transaction( _state: Option<&Self>, - rng: &mut dyn rand::RngCore, + _rng: &mut dyn rand::RngCore, padding: u64, ) -> ::Transaction { /// clippy appeasement for `RANDOM_TX_BASE_SIZE` const RANDOM_TX_BASE_SIZE: usize = 8; - let mut bytes = vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]; - rng.fill_bytes(&mut bytes); - VIDTransaction(bytes) + VIDTransaction(vec![0; RANDOM_TX_BASE_SIZE + (padding as usize)]) } } /// Implementation of [`NodeType`] for [`VDemoNode`] From 35487c22de4a01fa0cc4140bfd0286bad6ce8da4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 1 Oct 2023 00:20:23 +0000 Subject: [PATCH 36/37] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'fenix': 'github:nix-community/fenix/3605f6c31ac62e055c0ab0dbfa251fa96285109d' (2023-09-23) → 'github:nix-community/fenix/3116ee073ab3931c78328ca126224833c95e6227' (2023-09-30) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/2b580a1f3c7bf7f2dd6d1462282362b80a6a3d91' (2023-09-22) → 'github:rust-lang/rust-analyzer/4791a5de21735e3d9414d131a4f973da9bae0537' (2023-09-29) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/e12483116b3b51a185a33a272bf351e357ba9a99' (2023-09-21) → 'github:NixOS/nixpkgs/bd9b686c0168041aea600222be0805a0de6e6ab8' (2023-09-29) --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index c29e31ee27..99bccee207 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1695449989, - "narHash": "sha256-A4KxWCgaT1BSVY99o+FZ841U/5yf5hKJmztwrBdvboM=", + "lastModified": 1696054802, + "narHash": "sha256-VTON/WlYeyzFoYwwsb8KveqJJCfWEI6NtZYHcAFKBuo=", "owner": "nix-community", "repo": "fenix", - "rev": "3605f6c31ac62e055c0ab0dbfa251fa96285109d", + "rev": "3116ee073ab3931c78328ca126224833c95e6227", "type": "github" }, "original": { @@ -72,11 +72,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695318763, - "narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=", + "lastModified": 1695978539, + "narHash": "sha256-lta5HToBZMWZ2hl5CautNSUgIZViR41QxN7JKbMAjgQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e12483116b3b51a185a33a272bf351e357ba9a99", + "rev": "bd9b686c0168041aea600222be0805a0de6e6ab8", "type": "github" }, "original": { @@ -99,11 +99,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1695398941, - "narHash": "sha256-BejjVu84wXk8G1dZuu66r8kz567aAymfaiYgXpMRNqU=", + "lastModified": 1696014495, + "narHash": "sha256-TcDFXRK9weJ1yCQyo6zxRhLfYHe/GcXDbSUpiszNCuw=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "2b580a1f3c7bf7f2dd6d1462282362b80a6a3d91", + "rev": "4791a5de21735e3d9414d131a4f973da9bae0537", "type": "github" }, "original": { From 4d2a9a111b83b70b0302861b1ebe2e5684c48509 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:39:09 -0400 Subject: [PATCH 37/37] Bump generic-array from 0.14.7 to 1.0.0 (#1724) * Bump generic-array from 0.14.7 to 1.0.0 Bumps [generic-array](https://github.com/fizyk20/generic-array) from 0.14.7 to 1.0.0. - [Release notes](https://github.com/fizyk20/generic-array/releases) - [Changelog](https://github.com/fizyk20/generic-array/blob/master/CHANGELOG.md) - [Commits](https://github.com/fizyk20/generic-array/commits/1.0.0) --- updated-dependencies: - dependency-name: generic-array dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * set generic-array dep to 0.14.7, make it a shared workspace dep * update commit dep to latest main * update jellyfish dep to latest main --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gus Gutoski --- Cargo.lock | 10 ++++------ Cargo.toml | 5 +++++ crates/hotshot-qc/Cargo.toml | 2 +- crates/hotshot-stake-table/Cargo.toml | 2 +- crates/types/Cargo.toml | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f2c5e9a49..fd8522035a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1282,7 +1282,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "commit" version = "0.2.2" -source = "git+https://github.com/EspressoSystems/commit#100cb8f402e32d794b4d2213356227b7bfeb0e92" +source = "git+https://github.com/EspressoSystems/commit#5f1c28f1a109f2b36cf597e61a222614958db3b2" dependencies = [ "arbitrary", "ark-serialize 0.3.0", @@ -1290,7 +1290,6 @@ dependencies = [ "derivative", "derive_more", "funty", - "generic-array", "hex", "serde", "sha3", @@ -3270,7 +3269,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jf-primitives" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" +source = "git+https://github.com/EspressoSystems/jellyfish#1626a8448e7af8ea153241004375deff9fd961da" dependencies = [ "anyhow", "ark-bls12-377", @@ -3294,7 +3293,6 @@ dependencies = [ "digest 0.10.7", "displaydoc", "espresso-systems-common 0.4.0", - "generic-array", "hashbrown 0.13.2", "itertools 0.10.5", "jf-relation", @@ -3315,7 +3313,7 @@ dependencies = [ [[package]] name = "jf-relation" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" +source = "git+https://github.com/EspressoSystems/jellyfish#1626a8448e7af8ea153241004375deff9fd961da" dependencies = [ "ark-bls12-377", "ark-bls12-381", @@ -3341,7 +3339,7 @@ dependencies = [ [[package]] name = "jf-utils" version = "0.4.0-pre.0" -source = "git+https://github.com/EspressoSystems/jellyfish#30752c6c1af7b933e2536d7aeb991a40af4b806a" +source = "git+https://github.com/EspressoSystems/jellyfish#1626a8448e7af8ea153241004375deff9fd961da" dependencies = [ "ark-ec", "ark-ff", diff --git a/Cargo.toml b/Cargo.toml index 10990e7437..688e9c37d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,11 @@ either = { version = "1.8" } espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", tag = "0.4.1" } ethereum-types = { version = "0.14.1", features = ["impl-serde"] } futures = "0.3.28" + +# TODO generic-array should not be a direct dependency +# https://github.com/EspressoSystems/HotShot/issues/1850 +generic-array = { version = "0.14.7", features = ["serde"] } + jf-primitives = { git = "https://github.com/EspressoSystems/jellyfish" } jf-relation = { git = "https://github.com/EspressoSystems/jellyfish" } jf-utils = { git = "https://github.com/espressosystems/jellyfish" } diff --git a/crates/hotshot-qc/Cargo.toml b/crates/hotshot-qc/Cargo.toml index 0faa1f0a87..9c53fb335a 100644 --- a/crates/hotshot-qc/Cargo.toml +++ b/crates/hotshot-qc/Cargo.toml @@ -19,7 +19,7 @@ ark-std = { workspace = true } bincode = { workspace = true } bitvec = { workspace = true } ethereum-types = { workspace = true } -generic-array = "0.14.7" +generic-array = { workspace = true } hotshot-types = { path = "../types" } jf-primitives = { workspace = true } jf-relation = { workspace = true } diff --git a/crates/hotshot-stake-table/Cargo.toml b/crates/hotshot-stake-table/Cargo.toml index 8f11e4d66f..4059589a85 100644 --- a/crates/hotshot-stake-table/Cargo.toml +++ b/crates/hotshot-stake-table/Cargo.toml @@ -16,7 +16,7 @@ bitvec = { workspace = true } digest = { workspace = true } displaydoc = { version = "0.2.3", default-features = false } ethereum-types = { workspace = true } -generic-array = "0.14.7" +generic-array = { workspace = true } hotshot-types = { path = "../types" } jf-primitives = { workspace = true } jf-relation = { workspace = true } diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index dbc1b7b009..c0eb7a11e0 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -31,7 +31,7 @@ displaydoc = { version = "0.2.3", default-features = false } either = { workspace = true, features = ["serde"] } espresso-systems-common = { workspace = true } futures = { workspace = true } -generic-array = "0.14.7" +generic-array = { workspace = true } hex_fmt = "0.3.0" hotshot-constants = { path = "../constants" } hotshot-utils = { path = "../utils" }