Repository: ethereum/trin
Pull request #1781: feat(bridge): run trin ourselves instead of other process using json-rpc
Author: login: KolbyML
Created: 2025-04-25T07:16:37Z | Merged: 2025-04-30T19:30:38Z

### What was wrong?

- we are currently depending on a separate binary to run the bridge, this is annoying because if the Trin and Portal-bridge binary are out of sync you can get weird errors like if there is a change to ethportal-api, which is a common problem if you switch branches
- we are currently using HTTP JSON-RPC which is very slow for making all requests to trin which is extremely slow
- The beacon bridge test code isn't really testing anything, we already removed the history test code, I think we should remove it too.
- I need the performance gains for the state bridge, also a separate binary is bad UX. Ideally I don't want to need to add support for the census to use HTTP and HeaderOracle, like I did upstream in my Trin-Execution branch, this change will make it easier for me to downstream my changes

### How was it fixed?

- run Trin internally as a library instead of running a separately compiled trin binary
- remove beacon bridge test which really isn't testing much

 



Diff:
diff --git a/Cargo.lock b/Cargo.lock
index b10a0211d..d7d20deb2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4996,28 +4996,37 @@ dependencies = [
  "portalnet",
  "prometheus_exporter",
  "rand 0.8.5",
+ "regex",
  "reqwest",
  "reqwest-middleware",
  "reqwest-retry",
+ "reth-ipc",
  "revm",
  "revm-primitives",
  "rstest",
  "scraper",
  "serde",
  "serde_json",
- "serde_yaml",
  "ssz_types",
  "test-log",
  "thiserror 1.0.69",
  "tokio",
  "tracing",
+ "tracing-subscriber 0.3.19",
  "tracing-test",
+ "tree_hash",
+ "trin",
+ "trin-beacon",
  "trin-evm",
  "trin-execution",
+ "trin-history",
  "trin-metrics",
+ "trin-state",
+ "trin-storage",
  "trin-utils",
  "trin-validation",
  "url",
+ "utp-rs",
 ]
 
 [[package]]
diff --git a/bin/portal-bridge/Cargo.toml b/bin/portal-bridge/Cargo.toml
index b4ca6cc22..800641266 100644
--- a/bin/portal-bridge/Cargo.toml
+++ b/bin/portal-bridge/Cargo.toml
@@ -37,25 +37,34 @@ jsonrpsee = { workspace = true, features = [
 portalnet.workspace = true
 prometheus_exporter.workspace = true
 rand.workspace = true
+regex = "1.10.2"
 reqwest.workspace = true
 reqwest-middleware = { version = "0.3.3", features = ["json"] }
 reqwest-retry = "0.6.1"
+reth-ipc.workspace = true
 revm.workspace = true
 revm-primitives.workspace = true
 scraper.workspace = true
 serde = { workspace = true, features = ["rc"] }
 serde_json.workspace = true
-serde_yaml.workspace = true
 ssz_types.workspace = true
 thiserror.workspace = true
 tokio.workspace = true
 tracing.workspace = true
+tracing-subscriber.workspace = true
+tree_hash.workspace = true
+trin.workspace = true
+trin-beacon.workspace = true
+trin-history.workspace = true
+trin-state.workspace = true
+trin-storage.workspace = true
 trin-evm.workspace = true
 trin-execution.workspace = true
 trin-metrics.workspace = true
 trin-utils.workspace = true
 trin-validation.workspace = true
 url.workspace = true
+utp-rs.workspace = true
 
 [dev-dependencies]
 env_logger.workspace = true
diff --git a/bin/portal-bridge/README.md b/bin/portal-bridge/README.md
index 2831a8833..731b74533 100644
--- a/bin/portal-bridge/README.md
+++ b/bin/portal-bridge/README.md
@@ -4,7 +4,7 @@ Process to feed the portal network by gossiping data retrieved from a trusted pr
 
 ex.
 ```sh
-cargo run -p portal-bridge --release -- --executable-path ./target/debug/trin
+cargo run -p portal-bridge --release -- --mode e2hs --e2hs-range 100000-2000000
 ```
 
 ## Providers
@@ -32,7 +32,6 @@ cargo run -p portal-bridge --release -- --executable-path ./target/debug/trin
 #### Beacon Subnetwork
 
 - `"--mode latest"`: follow the head of the chain and gossip latest blocks
-- `"--mode test:/path/to/test_data.json"`: gossip content keys & values found in test file.
 
 #### State Subnetwork
 
@@ -47,12 +46,3 @@ You can specify the `--portal-subnetwork` flag for which network to run the brid
 - `"--portal-subnetwork beacon"`: Run the bridge for the beacon network.
 - `"--portal-subnetwork state"`: Run the bridge for the state network.
 Any pre-required subnetworks will automatically be enabled
-
-### Test File example
-
-```json
-[{
-	"content_key": "0x006251d65b8a8668efabe2f89c96a5b6332d83b3bbe585089ea6b2ab9b6754f5e9",
-	"content_value": "0x0800000023020000f90218a00409be8253ad6ac0eb2056bc94194c6ccb83c74f4292c40c82e2dc8203bdc759a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942a65aca4d5fc5b5c859090a6c34d164135398226a0afbf9bfd23008e8df44a83bb51ade45b993b3253fbce69cf7cec5d628eca6d45a0a7120e4bd136c0b6bdb0fa4990649f8c34d10d180dbd5ad6d03502ae92d32308a0d78aa953fedc7f7c112b2686d0b2b7e37eba716dd1f5d74ef3c8a37005f35215b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000004000000000000000000040000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000860b69dd9d66ce830f424a832fefd88303a68c8456bfb4e398d783010303844765746887676f312e352e31856c696e7578a0e962efb883f91286e4fc6fd12989a70f24c174bd087f472528137c4134af0a1a88e857c5acc15dd827cead98e305c70563000000000000000000000000000000000000000000000000be1b4a7a57f5316eea09c5e3e349141c46c1cb43664a815d28644cd74f282ca122360456d89447c0d586a8f5490922ea86b20e056879d64d87d104c14c0e594a6d800f67f5331ee2e511dc20e169c644b3df0f4c6b7c1717fc29d4844050b74044b506bf91edd14825aaec4f36fc5ad97b9eed9773aa2df15f80dff21eb668e24d61c29c3fda0fb425078a0479c5ea375ff95ad7780d0cdc87012009fd4a3dd003b06c7a28d6188e6be50ac544548cc7e3ee6cd07a8129f5c6d4d494b62ee8d96d26d0875bc87b56be0bf3e45846c0e3773abfccc239fdab29640b4e2aef297efcc6cb89b00a2566221cb4197ece3f66c24ea89969bd16265a74910aaf08d775116191117416b8799d0984f452a6fba19623442a7f199ef1627f1ae7295963a67db5534a292f98edbfb419ed85756abe76cd2d2bff8eb9b848b1e7b80b8274bbc469a36dce58b48ae57be6312bca843463ac45c54122a9f3fa9dca124b0fd50bce300708549c77b81b031278b9d193464f5e4b14769f6018055a457a577c508e811bcf55b297df3509f3db7e66ec68451e25acfbf935200e246f71e3c48240d00020000000000000000000000000000000000000000000000000000000000000"
-}]
-```
diff --git a/bin/portal-bridge/src/bridge/beacon.rs b/bin/portal-bridge/src/bridge/beacon.rs
index 81ab0fc2e..701084442 100644
--- a/bin/portal-bridge/src/bridge/beacon.rs
+++ b/bin/portal-bridge/src/bridge/beacon.rs
@@ -1,6 +1,5 @@
 use std::{
     cmp::Ordering,
-    path::PathBuf,
     sync::{Arc, Mutex as StdMutex},
     time::{Instant, SystemTime},
 };
@@ -25,16 +24,16 @@ use ethportal_api::{
         network::Subnetwork,
         portal_wire::OfferTrace,
     },
-    BeaconContentKey, BeaconContentValue, BeaconNetworkApiClient, ContentValue,
-    LightClientBootstrapKey, LightClientUpdatesByRangeKey, OverlayContentKey,
+    BeaconContentKey, BeaconContentValue, ContentValue, LightClientBootstrapKey,
+    LightClientUpdatesByRangeKey, OverlayContentKey,
 };
-use jsonrpsee::http_client::HttpClient;
 use ssz_types::VariableList;
 use tokio::{
     sync::Mutex,
     time::{interval, sleep, timeout, Duration, MissedTickBehavior},
 };
 use tracing::{error, info, warn, Instrument};
+use trin_beacon::network::BeaconNetwork;
 use trin_metrics::bridge::BridgeMetricsReporter;
 
 use super::{constants::SERVE_BLOCK_TIMEOUT, offer_report::OfferReport};
@@ -43,10 +42,7 @@ use crate::{
     census::Census,
     constants::BEACON_GENESIS_TIME,
     types::mode::BridgeMode,
-    utils::{
-        duration_until_next_update, expected_current_slot, read_test_assets_from_file,
-        BeaconTestAssets,
-    },
+    utils::{duration_until_next_update, expected_current_slot},
 };
 
 /// The number of slots in an epoch.
@@ -88,7 +84,7 @@ impl FinalizedBootstrap {
 pub struct BeaconBridge {
     consensus_api: ConsensusApi,
     mode: BridgeMode,
-    portal_client: HttpClient,
+    beacon_network: Arc<BeaconNetwork>,
     metrics: BridgeMetricsReporter,
     /// Used to request all interested enrs in the network.
     census: Census,
@@ -98,14 +94,14 @@ impl BeaconBridge {
     pub fn new(
         consensus_api: ConsensusApi,
         mode: BridgeMode,
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         census: Census,
     ) -> Self {
         let metrics = BridgeMetricsReporter::new("beacon".to_string(), &format!("{mode:?}"));
         Self {
             consensus_api,
             mode,
-            portal_client,
+            beacon_network,
             metrics,
             census,
         }
@@ -116,28 +112,12 @@ impl BeaconBridge {
 
         match self.mode.clone() {
             BridgeMode::Latest => self.launch_latest().await,
-            BridgeMode::Test(test_path) => self.launch_test(test_path).await,
             other => panic!("Beacon bridge mode {other:?} not implemented!"),
         }
 
         info!("Bridge mode: {:?} complete.", self.mode);
     }
 
-    async fn launch_test(&self, test_path: PathBuf) {
-        let assets: BeaconTestAssets = read_test_assets_from_file(test_path);
-
-        // test files have no slot number data, so report all gossiped content at height 0.
-        for asset in assets.0.into_iter() {
-            Self::spawn_offer_tasks(
-                self.portal_client.clone(),
-                asset.content_key.clone(),
-                asset.content_value().expect("Error getting content value"),
-                self.metrics.clone(),
-                self.census.clone(),
-            );
-        }
-    }
-
     ///  Get and serve the latest beacon data.
     async fn launch_latest(&self) {
         let current_period = Arc::new(Mutex::new(0));
@@ -183,13 +163,13 @@ impl BeaconBridge {
         let consensus_api_clone = self.consensus_api.clone();
 
         let metrics_clone = self.metrics.clone();
-        let portal_client_clone = self.portal_client.clone();
+        let beacon_network_clone = self.beacon_network.clone();
         let census_clone = self.census.clone();
 
         tokio::spawn(async move {
             if let Err(err) = Self::serve_light_client_bootstrap(
                 consensus_api_clone,
-                portal_client_clone,
+                beacon_network_clone,
                 finalized_bootstrap.clone(),
                 metrics_clone,
                 census_clone,
@@ -205,12 +185,12 @@ impl BeaconBridge {
         // Serve `LightClientUpdate` data
         let consensus_api_clone = self.consensus_api.clone();
         let metrics_clone = self.metrics.clone();
-        let portal_client_clone = self.portal_client.clone();
+        let beacon_network_clone = self.beacon_network.clone();
         let census_clone = self.census.clone();
         tokio::spawn(async move {
             if let Err(err) = Self::serve_light_client_update(
                 consensus_api_clone,
-                portal_client_clone,
+                beacon_network_clone,
                 current_period,
                 metrics_clone,
                 census_clone,
@@ -225,12 +205,12 @@ impl BeaconBridge {
         // Serve `LightClientFinalityUpdate` data
         let consensus_api_clone = self.consensus_api.clone();
         let metrics_clone = self.metrics.clone();
-        let portal_client_clone = self.portal_client.clone();
+        let beacon_network_clone = self.beacon_network.clone();
         let census_clone = self.census.clone();
         tokio::spawn(async move {
             if let Err(err) = Self::serve_light_client_finality_update(
                 consensus_api_clone,
-                portal_client_clone,
+                beacon_network_clone,
                 finalized_slot,
                 metrics_clone,
                 census_clone,
@@ -245,12 +225,12 @@ impl BeaconBridge {
         // Serve `LightClientOptimisticUpdate` data
         let consensus_api_clone = self.consensus_api.clone();
         let metrics_clone = self.metrics.clone();
-        let portal_client_clone = self.portal_client.clone();
+        let beacon_network_clone = self.beacon_network.clone();
         let census_clone = self.census.clone();
         tokio::spawn(async move {
             if let Err(err) = Self::serve_light_client_optimistic_update(
                 consensus_api_clone,
-                portal_client_clone,
+                beacon_network_clone,
                 metrics_clone,
                 census_clone,
             )
@@ -264,13 +244,13 @@ impl BeaconBridge {
         // Serve `HistoricalSummariesWithProof` data
         let consensus_api_clone = self.consensus_api.clone();
         let metrics_clone = self.metrics.clone();
-        let portal_client_clone = self.portal_client.clone();
+        let beacon_network_clone = self.beacon_network.clone();
         let census_clone = self.census.clone();
         let finalized_state_root_clone = finalized_state_root.clone();
         tokio::spawn(async move {
             if let Err(err) = Self::serve_historical_summaries_with_proof(
                 consensus_api_clone,
-                portal_client_clone,
+                beacon_network_clone,
                 metrics_clone,
                 census_clone,
                 finalized_state_root_clone,
@@ -286,7 +266,7 @@ impl BeaconBridge {
     /// Serve `LightClientBootstrap` data
     async fn serve_light_client_bootstrap(
         consensus_api: ConsensusApi,
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         finalized_bootstrap: Arc<Mutex<FinalizedBootstrap>>,
         metrics: BridgeMetricsReporter,
         census: Census,
@@ -328,7 +308,7 @@ impl BeaconBridge {
         });
 
         // Return the latest finalized block root if we successfully gossiped the latest bootstrap.
-        Self::spawn_offer_tasks(portal_client, content_key, content_value, metrics, census);
+        Self::spawn_offer_tasks(beacon_network, content_key, content_value, metrics, census);
         finalized_bootstrap.lock().await.finalized_block_root = latest_finalized_block_root;
         finalized_bootstrap.lock().await.in_progress = false;
 
@@ -337,7 +317,7 @@ impl BeaconBridge {
 
     async fn serve_light_client_update(
         consensus_api: ConsensusApi,
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         current_period: Arc<Mutex<u64>>,
         metrics: BridgeMetricsReporter,
         census: Census,
@@ -395,7 +375,7 @@ impl BeaconBridge {
         );
 
         // Update the current known period if we successfully gossiped the latest data.
-        Self::spawn_offer_tasks(portal_client, content_key, content_value, metrics, census);
+        Self::spawn_offer_tasks(beacon_network, content_key, content_value, metrics, census);
         *current_period.lock().await = expected_current_period;
 
         Ok(())
@@ -403,7 +383,7 @@ impl BeaconBridge {
 
     async fn serve_light_client_optimistic_update(
         consensus_api: ConsensusApi,
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         metrics: BridgeMetricsReporter,
         census: Census,
     ) -> anyhow::Result<()> {
@@ -416,13 +396,13 @@ impl BeaconBridge {
             LightClientOptimisticUpdateKey::new(update.signature_slot),
         );
         let content_value = BeaconContentValue::LightClientOptimisticUpdate(update.into());
-        Self::spawn_offer_tasks(portal_client, content_key, content_value, metrics, census);
+        Self::spawn_offer_tasks(beacon_network, content_key, content_value, metrics, census);
         Ok(())
     }
 
     async fn serve_light_client_finality_update(
         consensus_api: ConsensusApi,
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         finalized_slot: Arc<Mutex<u64>>,
         metrics: BridgeMetricsReporter,
         census: Census,
@@ -454,7 +434,7 @@ impl BeaconBridge {
         );
         let content_value = BeaconContentValue::LightClientFinalityUpdate(update.into());
 
-        Self::spawn_offer_tasks(portal_client, content_key, content_value, metrics, census);
+        Self::spawn_offer_tasks(beacon_network, content_key, content_value, metrics, census);
         *finalized_slot.lock().await = new_finalized_slot;
 
         Ok(())
@@ -462,7 +442,7 @@ impl BeaconBridge {
 
     async fn serve_historical_summaries_with_proof(
         consensus_api: ConsensusApi,
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         metrics: BridgeMetricsReporter,
         census: Census,
         finalized_state_root: Arc<Mutex<FinalizedBeaconState>>,
@@ -517,7 +497,7 @@ impl BeaconBridge {
         let content_value =
             BeaconContentValue::HistoricalSummariesWithProof(historical_summaries_with_proof);
 
-        Self::spawn_offer_tasks(portal_client, content_key, content_value, metrics, census);
+        Self::spawn_offer_tasks(beacon_network, content_key, content_value, metrics, census);
         finalized_state_root.lock().await.state_root = latest_finalized_state_root;
         finalized_state_root.lock().await.in_progress = false;
 
@@ -526,7 +506,7 @@ impl BeaconBridge {
 
     // spawn individual offer tasks of the content key for each interested enr found in Census
     fn spawn_offer_tasks(
-        portal_client: HttpClient,
+        beacon_network: Arc<BeaconNetwork>,
         content_key: BeaconContentKey,
         content_value: BeaconContentValue,
         metrics: BridgeMetricsReporter,
@@ -543,7 +523,7 @@ impl BeaconBridge {
         let encoded_content_value = content_value.encode();
         for peer in peers.clone() {
             let census = census.clone();
-            let portal_client = portal_client.clone();
+            let beacon_network = beacon_network.clone();
             let content_key = content_key.clone();
             let encoded_content_value = encoded_content_value.clone();
             let offer_report = offer_report.clone();
@@ -556,10 +536,9 @@ impl BeaconBridge {
 
                 let result = timeout(
                     SERVE_BLOCK_TIMEOUT,
-                    BeaconNetworkApiClient::trace_offer(
-                        &portal_client,
+                    beacon_network.overlay.send_offer_trace(
                         peer.enr.clone(),
-                        content_key.clone(),
+                        content_key.to_bytes(),
                         encoded_content_value,
                     ),
                 )
diff --git a/bin/portal-bridge/src/bridge/e2hs.rs b/bin/portal-bridge/src/bridge/e2hs.rs
index 1a8297304..cd2a395e1 100644
--- a/bin/portal-bridge/src/bridge/e2hs.rs
+++ b/bin/portal-bridge/src/bridge/e2hs.rs
@@ -14,12 +14,11 @@ use e2store::{
     utils::get_e2hs_files,
 };
 use ethportal_api::{
-    jsonrpsee::http_client::HttpClient,
     types::{
         execution::header_with_proof::HeaderWithProof, network::Subnetwork, portal_wire::OfferTrace,
     },
-    BlockBody, ContentValue, HistoryContentKey, HistoryContentValue, HistoryNetworkApiClient,
-    OverlayContentKey, RawContentValue, Receipts,
+    BlockBody, ContentValue, HistoryContentKey, HistoryContentValue, OverlayContentKey,
+    RawContentValue, Receipts,
 };
 use futures::{
     future::{join_all, JoinAll, Map},
@@ -37,6 +36,7 @@ use tokio::{
     time::{sleep, timeout},
 };
 use tracing::{debug, error, info, warn};
+use trin_history::network::HistoryNetwork;
 use trin_metrics::bridge::BridgeMetricsReporter;
 use trin_validation::header_validator::HeaderValidator;
 
@@ -67,7 +67,7 @@ pub struct E2HSBridge {
 
 impl E2HSBridge {
     pub async fn new(
-        portal_client: HttpClient,
+        history_network: Arc<HistoryNetwork>,
         offer_limit: usize,
         block_range: BlockRange,
         random_fill: bool,
@@ -87,7 +87,7 @@ impl E2HSBridge {
         let global_offer_report = Arc::new(Mutex::new(GlobalOfferReport::default()));
         let gossiper = Gossiper {
             census,
-            portal_client,
+            history_network,
             metrics,
             global_offer_report,
             offer_semaphore,
@@ -105,6 +105,7 @@ impl E2HSBridge {
 
     pub async fn launch(&self) {
         info!("Launching E2HS bridge");
+
         let epochs = block_range_to_epochs(self.block_range.start, self.block_range.end);
         let mut epoch_indexes: Vec<u64> = epochs.keys().cloned().sorted().collect();
         if self.random_fill {
@@ -118,7 +119,6 @@ impl E2HSBridge {
             // Start gossiping epoch
             let task = self.gossip_epoch(index, *block_range).await;
 
-            // Save task and make sure that previous task finished gossiping before we proceed.
             if let Some(previous_task) = latest_task.replace(task) {
                 previous_task.await;
             }
@@ -229,7 +229,7 @@ struct Gossiper {
     /// Used to request all interested enrs in the network.
     census: Census,
     /// Used to send RPC request to trin
-    portal_client: HttpClient,
+    history_network: Arc<HistoryNetwork>,
     /// Records and reports bridge metrics
     metrics: BridgeMetricsReporter,
     /// Global offer report for tallying total performance of history bridge
@@ -407,10 +407,9 @@ impl Gossiper {
 
         let result = timeout(
             SERVE_BLOCK_TIMEOUT,
-            HistoryNetworkApiClient::trace_offer(
-                &self.portal_client,
+            self.history_network.overlay.send_offer_trace(
                 peer.enr.clone(),
-                content_key.clone(),
+                content_key.to_bytes(),
                 raw_content_value,
             ),
         )
diff --git a/bin/portal-bridge/src/bridge/state.rs b/bin/portal-bridge/src/bridge/state.rs
index 6d3790103..7bbdc49af 100644
--- a/bin/portal-bridge/src/bridge/state.rs
+++ b/bin/portal-bridge/src/bridge/state.rs
@@ -9,11 +9,10 @@ use anyhow::ensure;
 use e2store::utils::get_e2ss_files;
 use eth_trie::{decode_node, node::Node, EthTrie, RootWithTrieDiff, Trie};
 use ethportal_api::{
-    jsonrpsee::http_client::HttpClient,
     types::{
         network::Subnetwork, portal_wire::OfferTrace, state_trie::account_state::AccountState,
     },
-    ContentValue, OverlayContentKey, StateContentKey, StateContentValue, StateNetworkApiClient,
+    ContentValue, OverlayContentKey, StateContentKey, StateContentValue,
 };
 use humanize_duration::{prelude::DurationExt, Truncate};
 use reqwest::{
@@ -49,6 +48,7 @@ use trin_execution::{
     utils::full_nibble_path_to_address_hash,
 };
 use trin_metrics::bridge::BridgeMetricsReporter;
+use trin_state::network::StateNetwork;
 use trin_utils::dir::{create_temp_dir, setup_data_dir};
 
 use super::{
@@ -63,7 +63,7 @@ use crate::{
 
 pub struct StateBridge {
     mode: BridgeMode,
-    portal_client: HttpClient,
+    state_network: Arc<StateNetwork>,
     metrics: BridgeMetricsReporter,
     /// Semaphore used to limit the amount of active offer transfers
     /// to make sure we don't overwhelm the trin client
@@ -80,7 +80,7 @@ pub struct StateBridge {
 impl StateBridge {
     pub async fn new(
         mode: BridgeMode,
-        portal_client: HttpClient,
+        state_network: Arc<StateNetwork>,
         offer_limit: usize,
         census: Census,
         bridge_id: BridgeId,
@@ -91,7 +91,7 @@ impl StateBridge {
         let global_offer_report = Arc::new(Mutex::new(GlobalOfferReport::default()));
         Ok(Self {
             mode,
-            portal_client,
+            state_network,
             metrics,
             offer_semaphore,
             census,
@@ -521,7 +521,7 @@ impl StateBridge {
         for peer in peers.clone() {
             let permit = self.acquire_offer_permit().await;
             let census = self.census.clone();
-            let portal_client = self.portal_client.clone();
+            let state_network = self.state_network.clone();
             let content_key = content_key.clone();
             let encoded_content_value = encoded_content_value.clone();
             let offer_report = offer_report.clone();
@@ -535,10 +535,9 @@ impl StateBridge {
 
                 let result = timeout(
                     SERVE_BLOCK_TIMEOUT,
-                    StateNetworkApiClient::trace_offer(
-                        &portal_client,
+                    state_network.overlay.send_offer_trace(
                         peer.enr.clone(),
-                        content_key.clone(),
+                        content_key.to_bytes(),
                         encoded_content_value,
                     ),
                 )
diff --git a/bin/portal-bridge/src/census/mod.rs b/bin/portal-bridge/src/census/mod.rs
index f0321243d..365f6def7 100644
--- a/bin/portal-bridge/src/census/mod.rs
+++ b/bin/portal-bridge/src/census/mod.rs
@@ -1,15 +1,13 @@
 use std::{collections::HashSet, time::Duration};
 
 use discv5::enr::NodeId;
-use ethportal_api::{
-    jsonrpsee::http_client::HttpClient,
-    types::{network::Subnetwork, portal_wire::OfferTrace},
-};
+use ethportal_api::types::{network::Subnetwork, portal_wire::OfferTrace};
 use network::{Network, NetworkAction, NetworkInitializationConfig, NetworkManager};
 use peer::PeerInfo;
 use thiserror::Error;
 use tokio::task::JoinHandle;
 use tracing::{error, info, Instrument};
+use trin::SubnetworkOverlays;
 
 use crate::cli::BridgeConfig;
 
@@ -34,7 +32,7 @@ pub enum CensusError {
 /// The census is responsible for maintaining a list of known peers in the network,
 /// checking their liveness, updating their data radius, iterating through their
 /// rfn to find new peers, and providing interested enrs for a given content id.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct Census {
     history: Network,
     state: Network,
@@ -46,11 +44,23 @@ impl Census {
     const SUPPORTED_SUBNETWORKS: [Subnetwork; 3] =
         [Subnetwork::Beacon, Subnetwork::History, Subnetwork::State];
 
-    pub fn new(client: HttpClient, bridge_config: &BridgeConfig) -> Self {
+    pub fn new(subnetwork_overlays: SubnetworkOverlays, bridge_config: &BridgeConfig) -> Self {
         Self {
-            history: Network::new(client.clone(), Subnetwork::History, bridge_config),
-            state: Network::new(client.clone(), Subnetwork::State, bridge_config),
-            beacon: Network::new(client.clone(), Subnetwork::Beacon, bridge_config),
+            history: Network::new(
+                subnetwork_overlays.clone(),
+                Subnetwork::History,
+                bridge_config,
+            ),
+            state: Network::new(
+                subnetwork_overlays.clone(),
+                Subnetwork::State,
+                bridge_config,
+            ),
+            beacon: Network::new(
+                subnetwork_overlays.clone(),
+                Subnetwork::Beacon,
+                bridge_config,
+            ),
             initialized: false,
         }
     }
diff --git a/bin/portal-bridge/src/census/network.rs b/bin/portal-bridge/src/census/network.rs
index 0cb015a28..5b5889500 100644
--- a/bin/portal-bridge/src/census/network.rs
+++ b/bin/portal-bridge/src/census/network.rs
@@ -4,12 +4,12 @@ use anyhow::{anyhow, bail};
 use discv5::enr::NodeId;
 use ethportal_api::{
     generate_random_node_ids,
-    jsonrpsee::http_client::HttpClient,
     types::{
-        network::Subnetwork, ping_extensions::decode::PingExtension, portal::PongInfo,
-        portal_wire::OfferTrace,
+        network::Subnetwork,
+        ping_extensions::decode::PingExtension,
+        portal_wire::{OfferTrace, Pong},
     },
-    BeaconNetworkApiClient, Enr, HistoryNetworkApiClient, StateNetworkApiClient,
+    Enr,
 };
 use futures::{future::JoinAll, StreamExt};
 use itertools::Itertools;
@@ -18,6 +18,7 @@ use tokio::{
     time::{Instant, Interval},
 };
 use tracing::{debug, error, info, warn};
+use trin::SubnetworkOverlays;
 
 use super::{
     peer::PeerInfo,
@@ -70,15 +71,19 @@ impl Default for NetworkInitializationConfig {
 ///
 /// The [Network::init] should be used to initialize our view of the network, and [NetworkManager]
 /// should be used in a background task to keep it up-to-date.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub(super) struct Network {
     peers: Peers<AdditiveWeight>,
-    client: HttpClient,
+    subnetwork_overlays: SubnetworkOverlays,
     subnetwork: Subnetwork,
 }
 
 impl Network {
-    pub fn new(client: HttpClient, subnetwork: Subnetwork, bridge_config: &BridgeConfig) -> Self {
+    pub fn new(
+        subnetwork_overlays: SubnetworkOverlays,
+        subnetwork: Subnetwork,
+        bridge_config: &BridgeConfig,
+    ) -> Self {
         if !matches!(
             subnetwork,
             Subnetwork::History | Subnetwork::Beacon | Subnetwork::State
@@ -91,7 +96,7 @@ impl Network {
                 AdditiveWeight::default(),
                 bridge_config.enr_offer_limit,
             )),
-            client,
+            subnetwork_overlays,
             subnetwork,
         }
     }
@@ -242,7 +247,7 @@ impl Network {
             return LivenessResult::Fail;
         };
 
-        let capabilities = match PingExtension::decode_json(
+        let capabilities = match PingExtension::decode_ssz(
             pong_info.payload_type,
             pong_info.payload,
         ) {
@@ -282,21 +287,6 @@ impl Network {
         LivenessResult::Pass
     }
 
-    async fn ping(&self, enr: &Enr) -> anyhow::Result<PongInfo> {
-        match self.subnetwork {
-            Subnetwork::History => {
-                HistoryNetworkApiClient::ping(&self.client, enr.clone(), None, None)
-            }
-            Subnetwork::State => StateNetworkApiClient::ping(&self.client, enr.clone(), None, None),
-            Subnetwork::Beacon => {
-                BeaconNetworkApiClient::ping(&self.client, enr.clone(), None, None)
-            }
-            _ => unreachable!("ping: unsupported subnetwork: {}", self.subnetwork),
-        }
-        .await
-        .map_err(|err| anyhow!(err))
-    }
-
     /// Fetches node's ENR.
     ///
     /// Should be used when ENR sequence returned by Ping request is higher than the one we know.
@@ -314,33 +304,88 @@ impl Network {
             .ok_or_else(|| anyhow!("fetch_enr: response doesn't contain requested NodeId"))
     }
 
-    async fn find_nodes(&self, enr: &Enr, distances: Vec<u16>) -> anyhow::Result<Vec<Enr>> {
+    pub async fn ping(&self, enr: &Enr) -> anyhow::Result<Pong> {
         match self.subnetwork {
             Subnetwork::History => {
-                HistoryNetworkApiClient::find_nodes(&self.client, enr.clone(), distances)
+                self.subnetwork_overlays
+                    .history()?
+                    .overlay
+                    .send_ping(enr.clone(), None, None)
+                    .await
             }
             Subnetwork::State => {
-                StateNetworkApiClient::find_nodes(&self.client, enr.clone(), distances)
+                self.subnetwork_overlays
+                    .state()?
+                    .overlay
+                    .send_ping(enr.clone(), None, None)
+                    .await
             }
             Subnetwork::Beacon => {
-                BeaconNetworkApiClient::find_nodes(&self.client, enr.clone(), distances)
+                self.subnetwork_overlays
+                    .beacon()?
+                    .overlay
+                    .send_ping(enr.clone(), None, None)
+                    .await
             }
-            _ => unreachable!("find_nodes: unsupported subnetwork: {}", self.subnetwork),
+            _ => unreachable!("ping: unsupported subnetwork: {}", self.subnetwork),
         }
-        .await
         .map_err(|err| anyhow!(err))
     }
 
-    async fn recursive_find_nodes(&self, node_id: NodeId) -> anyhow::Result<Vec<Enr>> {
+    pub async fn find_nodes(&self, enr: &Enr, distances: Vec<u16>) -> anyhow::Result<Vec<Enr>> {
+        Ok(match self.subnetwork {
+            Subnetwork::History => {
+                self.subnetwork_overlays
+                    .history()?
+                    .overlay
+                    .send_find_nodes(enr.clone(), distances)
+                    .await
+            }
+            Subnetwork::State => {
+                self.subnetwork_overlays
+                    .state()?
+                    .overlay
+                    .send_find_nodes(enr.clone(), distances)
+                    .await
+            }
+            Subnetwork::Beacon => {
+                self.subnetwork_overlays
+                    .beacon()?
+                    .overlay
+                    .send_find_nodes(enr.clone(), distances)
+                    .await
+            }
+            _ => unreachable!("find_nodes: unsupported subnetwork: {}", self.subnetwork),
+        }
+        .map_err(|err| anyhow!(err))?
+        .enrs
+        .into_iter()
+        .map(|enr| enr.into())
+        .collect())
+    }
+
+    pub async fn recursive_find_nodes(&self, node_id: NodeId) -> anyhow::Result<Vec<Enr>> {
         let enrs = match self.subnetwork {
             Subnetwork::History => {
-                HistoryNetworkApiClient::recursive_find_nodes(&self.client, node_id).await?
+                self.subnetwork_overlays
+                    .history()?
+                    .overlay
+                    .lookup_node(node_id)
+                    .await
             }
             Subnetwork::State => {
-                StateNetworkApiClient::recursive_find_nodes(&self.client, node_id).await?
+                self.subnetwork_overlays
+                    .state()?
+                    .overlay
+                    .lookup_node(node_id)
+                    .await
             }
             Subnetwork::Beacon => {
-                BeaconNetworkApiClient::recursive_find_nodes(&self.client, node_id).await?
+                self.subnetwork_overlays
+                    .beacon()?
+                    .overlay
+                    .lookup_node(node_id)
+                    .await
             }
             _ => unreachable!(
                 "recursive_find_nodes: unsupported subnetwork: {}",
diff --git a/bin/portal-bridge/src/cli.rs b/bin/portal-bridge/src/cli.rs
index c7d1e2157..ab6956cc5 100644
--- a/bin/portal-bridge/src/cli.rs
+++ b/bin/portal-bridge/src/cli.rs
@@ -2,21 +2,23 @@ use std::{net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc};
 
 use alloy::primitives::B256;
 use clap::Parser;
-use ethportal_api::types::{network::Subnetwork, network_spec::NetworkSpec};
+use ethportal_api::types::{distance::Distance, network::Subnetwork, network_spec::NetworkSpec};
 use portalnet::constants::{DEFAULT_DISCOVERY_PORT, DEFAULT_NETWORK, DEFAULT_WEB3_HTTP_PORT};
+use trin::NodeRuntimeConfig;
+use trin_storage::config::StorageCapacityConfig;
 use trin_utils::cli::{check_private_key_length, network_parser};
 use url::Url;
 
 use crate::{
     bridge::e2hs::BlockRange,
     constants::{DEFAULT_OFFER_LIMIT, DEFAULT_TOTAL_REQUEST_TIMEOUT},
+    handle::subnetworks_flag,
     types::mode::BridgeMode,
     DEFAULT_BASE_CL_ENDPOINT, DEFAULT_BASE_EL_ENDPOINT, FALLBACK_BASE_CL_ENDPOINT,
     FALLBACK_BASE_EL_ENDPOINT,
 };
 
 pub const DEFAULT_SUBNETWORK: &str = "history";
-pub const DEFAULT_EXECUTABLE_PATH: &str = "./target/debug/trin";
 
 /// The maximum number of peers to send each piece of content.
 ///
@@ -26,9 +28,6 @@ pub const ENR_OFFER_LIMIT: usize = 8;
 #[derive(Parser, Debug, Clone)]
 #[command(name = "Trin Bridge", about = "Feed the network")]
 pub struct BridgeConfig {
-    #[arg(long, help = "path to portalnet client executable", default_value = DEFAULT_EXECUTABLE_PATH)]
-    pub executable_path: PathBuf,
-
     #[arg(
         long,
         default_value = "latest",
@@ -87,7 +86,7 @@ pub struct BridgeConfig {
         long = "external-ip",
         help = "(Only use this if you are behind a NAT) The address which will be advertised to peers (in an ENR). Changing it does not change which address trin binds to, ex: 127.0.0.1"
     )]
-    pub external_ip: Option<String>,
+    pub external_ip: Option<SocketAddr>,
 
     #[arg(
         long = "private-key",
@@ -174,6 +173,22 @@ pub struct BridgeConfig {
     pub data_dir: Option<PathBuf>,
 }
 
+impl BridgeConfig {
+    pub fn as_node_runtime_config(&self, node_data_dir: PathBuf) -> NodeRuntimeConfig {
+        let portal_subnetworks = subnetworks_flag(self);
+        NodeRuntimeConfig {
+            portal_subnetworks: Arc::new(portal_subnetworks.clone()),
+            max_radius: Distance::ZERO,
+            enable_metrics_with_url: self.client_metrics_url,
+            storage_capacity_config: StorageCapacityConfig::Combined {
+                total_mb: 0,
+                subnetworks: portal_subnetworks,
+            },
+            node_data_dir,
+        }
+    }
+}
+
 /// Used to identify the bridge amongst a set of bridges,
 /// each responsible for offering a subset of the total content.
 #[derive(Parser, Debug, Clone)]
@@ -227,18 +242,7 @@ mod test {
 
     #[test]
     fn test_default_bridge_config() {
-        const EXECUTABLE_PATH: &str = "path/to/executable";
-        let bridge_config = BridgeConfig::parse_from([
-            "bridge",
-            "--executable-path",
-            EXECUTABLE_PATH,
-            "--portal-subnetwork",
-            "history",
-        ]);
-        assert_eq!(
-            bridge_config.executable_path,
-            PathBuf::from(EXECUTABLE_PATH)
-        );
+        let bridge_config = BridgeConfig::parse_from(["bridge", "--portal-subnetwork", "history"]);
         assert_eq!(bridge_config.mode, BridgeMode::Latest);
         assert_eq!(
             bridge_config.el_provider.to_string(),
@@ -261,19 +265,8 @@ mod test {
 
     #[test]
     fn test_bridge_config_with_epoch() {
-        const EXECUTABLE_PATH: &str = "path/to/executable";
         const MODE: &str = "snapshot:60";
-        let bridge_config = BridgeConfig::parse_from([
-            "bridge",
-            "--executable-path",
-            EXECUTABLE_PATH,
-            "--mode",
-            MODE,
-        ]);
-        assert_eq!(
-            bridge_config.executable_path,
-            PathBuf::from(EXECUTABLE_PATH)
-        );
+        let bridge_config = BridgeConfig::parse_from(["bridge", "--mode", MODE]);
         assert_eq!(bridge_config.mode, BridgeMode::Snapshot(60));
         assert_eq!(bridge_config.portal_subnetwork, Subnetwork::History);
     }
diff --git a/bin/portal-bridge/src/handle.rs b/bin/portal-bridge/src/handle.rs
index 2bc2907e4..3ee6006d2 100644
--- a/bin/portal-bridge/src/handle.rs
+++ b/bin/portal-bridge/src/handle.rs
@@ -1,52 +1,55 @@
-use ethportal_api::{types::network::Subnetwork, utils::bytes::hex_encode};
-use tokio::process::{Child, Command};
+use std::str::FromStr;
+
+use anyhow::anyhow;
+use ethportal_api::types::network::Subnetwork;
+use portalnet::{
+    bootnodes::Bootnodes,
+    config::{PortalnetConfig, DISCV5_SESSION_CACHE_CAPACITY},
+    utils::db::configure_node_data_dir,
+};
+use trin::{run_trin, SubnetworkOverlays};
+use trin_utils::dir::setup_data_dir;
 
 use crate::cli::BridgeConfig;
 
-pub fn build_trin(bridge_config: &BridgeConfig) -> anyhow::Result<Child> {
-    if !bridge_config.executable_path.is_file() {
-        return Err(anyhow::anyhow!(
-            "Trin executable path is not a file: {:?}",
-            bridge_config.executable_path
-        ));
-    }
-    let rpc_port = bridge_config.base_rpc_port;
-    let udp_port = bridge_config.base_discovery_port;
-    let private_key = hex_encode(bridge_config.private_key);
-    let mut command = Command::new(bridge_config.executable_path.clone());
-
-    command
-        .kill_on_drop(true)
-        .args(["--ephemeral"])
-        .args(["--no-upnp"])
-        .args(["--mb", "0"])
-        .args(["--web3-transport", "http"])
-        .args(["--network", &bridge_config.network.network().to_string()])
-        .args(["--portal-subnetworks", &subnetworks_flag(bridge_config)])
-        .args(["--unsafe-private-key", &private_key])
-        .args(["--web3-http-address", &format!("http://0.0.0.0:{rpc_port}")])
-        .args(["--discovery-port", &format!("{udp_port}")])
-        .args(["--bootnodes", &bridge_config.bootnodes])
-        .args([
-            "--utp-transfer-limit",
-            &bridge_config.offer_limit.to_string(),
-        ]);
-    if let Some(ip) = bridge_config.external_ip.clone() {
-        command.args(["--external-address", &format!("{ip}:{udp_port}")]);
-    }
-    if let Some(client_metrics_url) = bridge_config.client_metrics_url {
-        let url: String = client_metrics_url.to_string();
-        command.args(["--enable-metrics-with-url", &url]);
-    }
+const APP_NAME: &str = "portal-bridge";
+
+pub async fn start_trin(bridge_config: &BridgeConfig) -> anyhow::Result<SubnetworkOverlays> {
+    // Setup temp trin data directory if we're in ephemeral mode
+    let trin_data_dir = setup_data_dir(APP_NAME, None, true)?;
+
+    // Configure node data dir based on the provided private key
+    let (node_data_dir, private_key) = configure_node_data_dir(
+        &trin_data_dir,
+        Some(bridge_config.private_key),
+        bridge_config.network.network(),
+    )?;
+
+    let portalnet_config = PortalnetConfig {
+        external_addr: bridge_config.external_ip,
+        private_key,
+        listen_port: bridge_config.base_discovery_port,
+        bootnodes: Bootnodes::from_str(&bridge_config.bootnodes)?
+            .to_enrs(bridge_config.network.network()),
+        no_stun: false,
+        no_upnp: true,
+        discv5_session_cache_capacity: DISCV5_SESSION_CACHE_CAPACITY,
+        disable_poke: false,
+        trusted_block_root: None,
+        utp_transfer_limit: bridge_config.offer_limit,
+    };
+    let node_runtime_config = bridge_config.as_node_runtime_config(node_data_dir);
 
-    Ok(command.spawn()?)
+    run_trin(portalnet_config, node_runtime_config)
+        .await
+        .map_err(|err| anyhow!("Failed to run trin error: {err:?}"))
 }
 
 /// Returns the subnetwork flag to be passed to the trin handle.
 ///
 /// This is a union of required subnetworks for each subnetwork from the config.
-pub fn subnetworks_flag(bridge_config: &BridgeConfig) -> String {
-    let subnetworks = match bridge_config.portal_subnetwork {
+pub fn subnetworks_flag(bridge_config: &BridgeConfig) -> Vec<Subnetwork> {
+    match bridge_config.portal_subnetwork {
         Subnetwork::Beacon => vec![Subnetwork::Beacon],
         // History requires beacon and history
         Subnetwork::History => vec![Subnetwork::Beacon, Subnetwork::History],
@@ -54,7 +57,4 @@ pub fn subnetworks_flag(bridge_config: &BridgeConfig) -> String {
         Subnetwork::State => vec![Subnetwork::Beacon, Subnetwork::History, Subnetwork::State],
         subnetwork => panic!("Unsupported subnetwork: {subnetwork:?}"),
     }
-    .into_iter()
-    .map(|subnetwork| subnetwork.to_cli_arg());
-    Vec::from_iter(subnetworks).join(",")
 }
diff --git a/bin/portal-bridge/src/main.rs b/bin/portal-bridge/src/main.rs
index 73a8c5bf7..7fcc734cd 100644
--- a/bin/portal-bridge/src/main.rs
+++ b/bin/portal-bridge/src/main.rs
@@ -1,18 +1,16 @@
+use std::future::Future;
+
 use clap::Parser;
-use ethportal_api::{
-    jsonrpsee::http_client::{HttpClient, HttpClientBuilder},
-    types::network::Subnetwork,
-};
+use ethportal_api::types::network::Subnetwork;
 use portal_bridge::{
     api::consensus::ConsensusApi,
     bridge::{beacon::BeaconBridge, e2hs::E2HSBridge, state::StateBridge},
     census::Census,
     cli::BridgeConfig,
-    handle::build_trin,
+    handle::start_trin,
     types::mode::BridgeMode,
 };
-use tokio::time::{sleep, Duration};
-use tracing::Instrument;
+use tracing::{info, warn, Instrument};
 use trin_utils::log::init_tracing_logger;
 
 #[tokio::main]
@@ -27,22 +25,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
 
     // start the bridge client, need to keep the handle alive
     // for bridge to work inside docker containers
-    let handle = build_trin(&bridge_config).map_err(|e| e.to_string())?;
-
-    let web3_http_address = format!("http://127.0.0.1:{}", bridge_config.base_rpc_port);
-    sleep(Duration::from_secs(10)).await;
-
-    let portal_client: HttpClient = HttpClientBuilder::default()
-        // increase default timeout to allow for trace_gossip requests that can take a long
-        // time
-        .request_timeout(Duration::from_secs(120))
-        .build(web3_http_address.clone())
-        .map_err(|e| e.to_string())?;
+    let subnetwork_overlays = start_trin(&bridge_config)
+        .await
+        .map_err(|err| err.to_string())?;
 
     let census_handle = match bridge_config.portal_subnetwork {
         Subnetwork::Beacon => {
             // Create and initialize the census to acquire critical view of network before gossiping
-            let mut census = Census::new(portal_client.clone(), &bridge_config);
+            let mut census = Census::new(subnetwork_overlays.clone(), &bridge_config);
             let census_handle = census.init([Subnetwork::Beacon]).await?;
 
             let bridge_mode = bridge_config.mode.clone();
@@ -52,14 +42,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 bridge_config.request_timeout,
             )
             .await?;
-            let portal_client_clone = portal_client.clone();
+            let beacon_network = subnetwork_overlays
+                .beacon
+                .expect("Beacon network not found in SubnetworkOverlays");
             let beacon_bridge =
-                BeaconBridge::new(consensus_api, bridge_mode, portal_client_clone, census);
+                BeaconBridge::new(consensus_api, bridge_mode, beacon_network, census);
+
+            run_with_shutdown(
+                beacon_bridge
+                    .launch()
+                    .instrument(tracing::trace_span!("beacon")),
+            )
+            .await;
 
-            beacon_bridge
-                .launch()
-                .instrument(tracing::trace_span!("beacon"))
-                .await;
             census_handle
         }
         Subnetwork::History => {
@@ -70,21 +65,28 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                     };
                     // Create and initialize the census to acquire critical view of network before
                     // gossiping
-                    let mut census = Census::new(portal_client.clone(), &bridge_config);
+                    let mut census = Census::new(subnetwork_overlays.clone(), &bridge_config);
                     let census_handle = census.init([Subnetwork::History]).await?;
 
+                    let history_network = subnetwork_overlays
+                        .history
+                        .expect("History network not found in SubnetworkOverlays");
                     let e2hs_bridge = E2HSBridge::new(
-                        portal_client,
+                        history_network,
                         bridge_config.offer_limit,
                         e2hs_range,
                         bridge_config.e2hs_randomize,
                         census,
                     )
                     .await?;
-                    e2hs_bridge
-                        .launch()
-                        .instrument(tracing::trace_span!("history(e2hs)"))
-                        .await;
+
+                    run_with_shutdown(
+                        e2hs_bridge
+                            .launch()
+                            .instrument(tracing::trace_span!("history(e2hs)")),
+                    )
+                    .await;
+
                     census_handle
                 }
                 _ => panic!("Unsupported bridge mode for History network"),
@@ -92,12 +94,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
         }
         Subnetwork::State => {
             // Create and initialize the census to acquire critical view of network before gossiping
-            let mut census = Census::new(portal_client.clone(), &bridge_config);
+            let mut census = Census::new(subnetwork_overlays.clone(), &bridge_config);
             let census_handle = census.init([Subnetwork::State]).await?;
-
+            let state_network = subnetwork_overlays
+                .state
+                .expect("State network not found in SubnetworkOverlays");
             let state_bridge = StateBridge::new(
                 bridge_config.mode.clone(),
-                portal_client.clone(),
+                state_network,
                 bridge_config.offer_limit,
                 census,
                 bridge_config.bridge_id,
@@ -105,10 +109,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
             )
             .await?;
 
-            state_bridge
-                .launch()
-                .instrument(tracing::trace_span!("state"))
-                .await;
+            run_with_shutdown(
+                state_bridge
+                    .launch()
+                    .instrument(tracing::trace_span!("state")),
+            )
+            .await;
+
             census_handle
         }
         _ => {
@@ -119,8 +126,31 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
         }
     };
 
-    drop(handle);
     census_handle.abort();
     drop(census_handle);
     Ok(())
 }
+
+/// Runs a bridge future with a shutdown handler.
+///
+/// Pass the bridge's `launch()` future into this.
+pub async fn run_with_shutdown<F>(bridge_future: F)
+where
+    F: Future<Output = ()>,
+{
+    let shutdown_handle = tokio::spawn(async {
+        tokio::signal::ctrl_c()
+            .await
+            .expect("Failed to listen for Ctrl+C");
+        info!("Ctrl+C received. Initiating shutdown...");
+    });
+
+    tokio::select! {
+        _ = bridge_future  => {
+            info!("Finished all bridge tasks");
+        }
+        _ = shutdown_handle => {
+            warn!("Shutdown signal received during bridge execution.");
+        }
+    }
+}
diff --git a/bin/portal-bridge/src/types/mode.rs b/bin/portal-bridge/src/types/mode.rs
index bfccfd727..170eae6c5 100644
--- a/bin/portal-bridge/src/types/mode.rs
+++ b/bin/portal-bridge/src/types/mode.rs
@@ -1,4 +1,4 @@
-use std::{path::PathBuf, str::FromStr};
+use std::str::FromStr;
 
 /// Used to help decode cli args identifying the desired bridge mode.
 /// - Latest: tracks the latest header
@@ -13,7 +13,6 @@ pub enum BridgeMode {
     E2HS,
     Single(ModeType),
     Snapshot(u64),
-    Test(PathBuf),
 }
 
 type ParseError = String;
@@ -41,11 +40,6 @@ impl FromStr for BridgeMode {
                             .map_err(|_| "Invalid snapshot arg: snapshot number")?;
                         Ok(BridgeMode::Snapshot(snapshot))
                     }
-                    "test" => {
-                        let path =
-                            PathBuf::from_str(&val[1..]).map_err(|_| "Invalid test asset path")?;
-                        Ok(BridgeMode::Test(path))
-                    }
                     _ => Err("Invalid bridge mode arg: type prefix".to_string()),
                 }
             }
@@ -103,10 +97,6 @@ mod test {
 
     #[rstest]
     #[case("latest", BridgeMode::Latest)]
-    #[case(
-        "test:/usr/eth/test.json",
-        BridgeMode::Test(PathBuf::from("/usr/eth/test.json"))
-    )]
     fn test_mode_flag(#[case] actual: String, #[case] expected: BridgeMode) {
         let bridge_mode = BridgeMode::from_str(&actual).unwrap();
         assert_eq!(bridge_mode, expected);
diff --git a/bin/portal-bridge/src/utils.rs b/bin/portal-bridge/src/utils.rs
index b1d27eff7..144f4ee9a 100644
--- a/bin/portal-bridge/src/utils.rs
+++ b/bin/portal-bridge/src/utils.rs
@@ -1,18 +1,9 @@
-use std::{
-    ops::Deref,
-    path::PathBuf,
-    time::{SystemTime, UNIX_EPOCH},
-};
+use std::time::{SystemTime, UNIX_EPOCH};
 
 use alloy::primitives::B256;
-use anyhow::anyhow;
 use chrono::Duration;
 use discv5::enr::{CombinedKey, Enr, NodeId};
-use ethportal_api::{
-    types::network_spec::network_spec, utils::bytes::hex_encode, BeaconContentKey,
-    BeaconContentValue, ContentValue, RawContentValue,
-};
-use serde::{Deserialize, Serialize};
+use ethportal_api::{types::network_spec::network_spec, utils::bytes::hex_encode};
 
 /// Generates a set of N private keys, with node ids that are equally spaced
 /// around the 256-bit keys space.
@@ -58,50 +49,6 @@ fn random_node_id() -> (NodeId, CombinedKey) {
     (enr.node_id(), random_private_key)
 }
 
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct BeaconTestAssets(pub Vec<BeaconAsset>);
-
-impl Deref for BeaconTestAssets {
-    type Target = Vec<BeaconAsset>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct BeaconAsset {
-    pub content_key: BeaconContentKey,
-    content_value: RawContentValue,
-}
-
-impl BeaconAsset {
-    pub fn content_value(&self) -> anyhow::Result<BeaconContentValue> {
-        BeaconContentValue::decode(&self.content_key, &self.content_value).map_err(|err| {
-            anyhow!(
-                "Unable to parse beacon content value: {}. Error: {err}",
-                self.content_value
-            )
-        })
-    }
-}
-
-pub fn read_test_assets_from_file(test_path: PathBuf) -> BeaconTestAssets {
-    let extension = test_path
-        .extension()
-        .and_then(|path| path.to_str())
-        .expect("Unable to parse test path extension")
-        .to_string();
-    let test_asset = std::fs::read_to_string(test_path).expect("Error reading test asset.");
-
-    let assets: BeaconTestAssets = match &extension[..] {
-        "json" => serde_json::from_str(&test_asset).expect("Unable to parse json test asset."),
-        "yaml" => serde_yaml::from_str(&test_asset).expect("Unable to parse yaml test asset."),
-        _ => panic!("Invalid file extension"),
-    };
-
-    assets
-}
 /// Gets the duration until the next light client update
 /// Updates are scheduled for 4 seconds into each slot
 pub fn duration_until_next_update(genesis_time: u64, now: SystemTime) -> Duration {
diff --git a/bin/trin/src/cli.rs b/bin/trin/src/cli.rs
index 0061aca0a..1ab009646 100644
--- a/bin/trin/src/cli.rs
+++ b/bin/trin/src/cli.rs
@@ -31,11 +31,13 @@ use trin_utils::cli::{
 };
 use url::Url;
 
+use crate::run::NodeRuntimeConfig;
+
 const DEFAULT_SUBNETWORKS: &str = "beacon,history";
 /// Default max radius value percentage out of 100.
 const DEFAULT_MAX_RADIUS: &str = "5";
-pub const DEFAULT_STORAGE_CAPACITY_MB: &str = "1000";
-pub const DEFAULT_WEB3_TRANSPORT: &str = "ipc";
+const DEFAULT_STORAGE_CAPACITY_MB: &str = "1000";
+const DEFAULT_WEB3_TRANSPORT: &str = "ipc";
 
 #[derive(Parser, Debug, Clone)]
 #[command(name = APP_NAME,
@@ -381,6 +383,31 @@ impl TrinConfig {
             },
         }
     }
+
+    pub fn as_portalnet_config(&self, private_key: B256) -> PortalnetConfig {
+        PortalnetConfig {
+            external_addr: self.external_addr,
+            private_key,
+            listen_port: self.discovery_port,
+            bootnodes: self.bootnodes.to_enrs(self.network.network()),
+            no_stun: self.no_stun,
+            no_upnp: self.no_upnp,
+            discv5_session_cache_capacity: DISCV5_SESSION_CACHE_CAPACITY,
+            disable_poke: self.disable_poke,
+            trusted_block_root: self.trusted_block_root,
+            utp_transfer_limit: self.utp_transfer_limit,
+        }
+    }
+
+    pub fn as_node_runtime_config(&self, node_data_dir: PathBuf) -> NodeRuntimeConfig {
+        NodeRuntimeConfig {
+            portal_subnetworks: self.portal_subnetworks.clone(),
+            storage_capacity_config: self.storage_capacity_config(),
+            max_radius: self.max_radius,
+            enable_metrics_with_url: self.enable_metrics_with_url,
+            node_data_dir,
+        }
+    }
 }
 
 fn check_trusted_block_root(trusted_root: &str) -> Result<B256, String> {
@@ -418,27 +445,9 @@ impl fmt::Display for TrinConfig {
     }
 }
 
-impl TrinConfig {
-    pub fn to_portalnet_config(&self, private_key: B256) -> PortalnetConfig {
-        PortalnetConfig {
-            external_addr: self.external_addr,
-            private_key,
-            listen_port: self.discovery_port,
-            bootnodes: self.bootnodes.to_enrs(self.network.network()),
-            no_stun: self.no_stun,
-            no_upnp: self.no_upnp,
-            discv5_session_cache_capacity: DISCV5_SESSION_CACHE_CAPACITY,
-            disable_poke: self.disable_poke,
-            trusted_block_root: self.trusted_block_root,
-            utp_transfer_limit: self.utp_transfer_limit,
-        }
-    }
-}
-
 impl From<&TrinConfig> for RpcConfig {
     fn from(config: &TrinConfig) -> Self {
         RpcConfig {
-            portal_subnetworks: config.portal_subnetworks.clone(),
             web3_transport: config.web3_transport.clone(),
             web3_ipc_path: config.web3_ipc_path.clone(),
             web3_http_address: config.web3_http_address.clone(),
diff --git a/bin/trin/src/handle.rs b/bin/trin/src/handle.rs
new file mode 100644
index 000000000..db989f22b
--- /dev/null
+++ b/bin/trin/src/handle.rs
@@ -0,0 +1,42 @@
+use std::sync::Arc;
+
+use anyhow::bail;
+use rpc::RpcServerHandle;
+use trin_beacon::network::BeaconNetwork;
+use trin_history::network::HistoryNetwork;
+use trin_state::network::StateNetwork;
+
+pub struct TrinHandle {
+    pub rpc_server_handle: RpcServerHandle,
+    pub subnetwork_overlays: SubnetworkOverlays,
+}
+
+#[derive(Default, Clone)]
+pub struct SubnetworkOverlays {
+    pub history: Option<Arc<HistoryNetwork>>,
+    pub state: Option<Arc<StateNetwork>>,
+    pub beacon: Option<Arc<BeaconNetwork>>,
+}
+
+impl SubnetworkOverlays {
+    pub fn history(&self) -> anyhow::Result<Arc<HistoryNetwork>> {
+        match &self.history {
+            Some(history) => Ok(history.clone()),
+            None => bail!("History network is not available"),
+        }
+    }
+
+    pub fn state(&self) -> anyhow::Result<Arc<StateNetwork>> {
+        match &self.state {
+            Some(state) => Ok(state.clone()),
+            None => bail!("State network is not available"),
+        }
+    }
+
+    pub fn beacon(&self) -> anyhow::Result<Arc<BeaconNetwork>> {
+        match &self.beacon {
+            Some(beacon) => Ok(beacon.clone()),
+            None => bail!("Beacon network is not available"),
+        }
+    }
+}
diff --git a/bin/trin/src/lib.rs b/bin/trin/src/lib.rs
index c9464d9ff..4bcc6cd86 100644
--- a/bin/trin/src/lib.rs
+++ b/bin/trin/src/lib.rs
@@ -1,192 +1,10 @@
 #![warn(clippy::unwrap_used)]
 #![warn(clippy::uninlined_format_args)]
 
-pub mod cli;
+mod cli;
+mod handle;
+mod run;
 
-use std::sync::Arc;
-
-use cli::TrinConfig;
-use ethportal_api::{
-    types::{distance::Distance, network::Subnetwork},
-    version::get_trin_version,
-};
-use portalnet::{
-    discovery::{Discovery, Discv5UdpSocket},
-    events::PortalnetEvents,
-    utils::db::{configure_node_data_dir, configure_trin_data_dir},
-};
-use rpc::{launch_jsonrpc_server, RpcServerHandle};
-use tokio::sync::{mpsc, RwLock};
-use tracing::info;
-use tree_hash::TreeHash;
-use trin_beacon::initialize_beacon_network;
-use trin_history::initialize_history_network;
-use trin_state::initialize_state_network;
-use trin_storage::PortalStorageConfigFactory;
-#[cfg(windows)]
-use trin_utils::cli::Web3TransportType;
-use trin_validation::oracle::HeaderOracle;
-use utp_rs::socket::UtpSocket;
-
-pub async fn run_trin(
-    trin_config: TrinConfig,
-) -> Result<RpcServerHandle, Box<dyn std::error::Error>> {
-    // Panic early on a windows build that is trying to use IPC, which is unsupported for now
-    // Make sure not to panic on non-windows configurations.
-    #[cfg(windows)]
-    if let Web3TransportType::IPC = trin_config.web3_transport {
-        panic!("Tokio doesn't support Windows Unix Domain Sockets IPC, use --web3-transport http");
-    }
-
-    let trin_version = get_trin_version();
-    info!("Launching Trin: v{trin_version}");
-    info!(config = %trin_config, "With:");
-
-    // Setup temp trin data directory if we're in ephemeral mode
-    let trin_data_dir =
-        configure_trin_data_dir(trin_config.data_dir.clone(), trin_config.ephemeral)?;
-
-    // Configure node data dir based on the provided private key
-    let (node_data_dir, private_key) = configure_node_data_dir(
-        &trin_data_dir,
-        trin_config.private_key,
-        trin_config.network.network(),
-    )?;
-
-    let portalnet_config = trin_config.to_portalnet_config(private_key);
-
-    // Initialize base discovery protocol
-    let mut discovery = Discovery::new(portalnet_config.clone())?;
-    let talk_req_rx = discovery.start().await?;
-    let discovery = Arc::new(discovery);
-
-    // Initialize prometheus metrics
-    if let Some(addr) = trin_config.enable_metrics_with_url {
-        prometheus_exporter::start(addr)?;
-    }
-
-    // Initialize validation oracle
-    let header_oracle = HeaderOracle::default();
-    info!(
-        hash_tree_root = %header_oracle.header_validator.pre_merge_acc.tree_hash_root(),
-        "Loaded pre-merge accumulator."
-    );
-    let header_oracle = Arc::new(RwLock::new(header_oracle));
-
-    // Initialize and spawn uTP socket
-    let (utp_talk_reqs_tx, utp_talk_reqs_rx) = mpsc::unbounded_channel();
-
-    let discv5_utp_socket = Discv5UdpSocket::new(Arc::clone(&discovery), utp_talk_reqs_rx);
-    let utp_socket = UtpSocket::with_socket(discv5_utp_socket);
-    let utp_socket = Arc::new(utp_socket);
-
-    let storage_config_factory = PortalStorageConfigFactory::new(
-        trin_config.storage_capacity_config(),
-        discovery.local_enr().node_id(),
-        node_data_dir,
-    )?;
-
-    // Initialize state sub-network service and event handlers, if selected
-    let (state_handler, state_network_task, state_event_tx, state_jsonrpc_tx, state_event_stream) =
-        if trin_config.portal_subnetworks.contains(&Subnetwork::State) {
-            initialize_state_network(
-                &discovery,
-                utp_socket.clone(),
-                portalnet_config.clone(),
-                storage_config_factory.create(&Subnetwork::State, trin_config.max_radius)?,
-                header_oracle.clone(),
-            )
-            .await?
-        } else {
-            (None, None, None, None, None)
-        };
-
-    // Initialize trin-beacon sub-network service and event handlers, if selected
-    let (
-        beacon_handler,
-        beacon_network_task,
-        beacon_event_tx,
-        beacon_jsonrpc_tx,
-        beacon_event_stream,
-    ) = if trin_config.portal_subnetworks.contains(&Subnetwork::Beacon) {
-        initialize_beacon_network(
-            &discovery,
-            utp_socket.clone(),
-            portalnet_config.clone(),
-            storage_config_factory.create(&Subnetwork::Beacon, Distance::MAX)?,
-            header_oracle.clone(),
-        )
-        .await?
-    } else {
-        (None, None, None, None, None)
-    };
-
-    // Initialize chain history sub-network service and event handlers, if selected
-    let (
-        history_handler,
-        history_network_task,
-        history_event_tx,
-        history_jsonrpc_tx,
-        history_event_stream,
-    ) = if trin_config
-        .portal_subnetworks
-        .contains(&Subnetwork::History)
-    {
-        initialize_history_network(
-            &discovery,
-            utp_socket.clone(),
-            portalnet_config.clone(),
-            storage_config_factory.create(&Subnetwork::History, trin_config.max_radius)?,
-            header_oracle.clone(),
-        )
-        .await?
-    } else {
-        (None, None, None, None, None)
-    };
-
-    // Launch JSON-RPC server
-    let jsonrpc_discovery = Arc::clone(&discovery);
-    let rpc_handle: RpcServerHandle = launch_jsonrpc_server(
-        (&trin_config).into(),
-        jsonrpc_discovery,
-        history_jsonrpc_tx,
-        state_jsonrpc_tx,
-        beacon_jsonrpc_tx,
-    )
-    .await?;
-
-    if let Some(handler) = state_handler {
-        tokio::spawn(async move { handler.handle_client_queries().await });
-    }
-    if let Some(handler) = history_handler {
-        tokio::spawn(async move { handler.handle_client_queries().await });
-    }
-    if let Some(handler) = beacon_handler {
-        tokio::spawn(async move { handler.handle_client_queries().await });
-    }
-
-    // Spawn main portal events handler
-    tokio::spawn(async move {
-        let events = PortalnetEvents::new(
-            talk_req_rx,
-            (history_event_tx, history_event_stream),
-            (state_event_tx, state_event_stream),
-            (beacon_event_tx, beacon_event_stream),
-            utp_talk_reqs_tx,
-        )
-        .await;
-        events.start().await;
-    });
-
-    if let Some(network) = history_network_task {
-        tokio::spawn(network);
-    }
-    if let Some(network) = state_network_task {
-        tokio::spawn(network);
-    }
-    if let Some(network) = beacon_network_task {
-        tokio::spawn(network);
-    }
-
-    Ok(rpc_handle)
-}
+pub use cli::TrinConfig;
+pub use handle::{SubnetworkOverlays, TrinHandle};
+pub use run::{run_trin, run_trin_from_trin_config, run_trin_with_rpc, NodeRuntimeConfig};
diff --git a/bin/trin/src/main.rs b/bin/trin/src/main.rs
index c4171f95a..41fe2eb21 100644
--- a/bin/trin/src/main.rs
+++ b/bin/trin/src/main.rs
@@ -2,7 +2,7 @@
 
 use ethportal_api::types::network_spec::set_network_spec;
 use tracing::error;
-use trin::{cli::TrinConfig, run_trin};
+use trin::{run_trin_from_trin_config, TrinConfig};
 use trin_utils::log::init_tracing_logger;
 
 #[tokio::main]
@@ -10,13 +10,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     init_tracing_logger();
     let trin_config = TrinConfig::from_cli();
     set_network_spec(trin_config.network.clone());
-    let rpc_handle = run_trin(trin_config).await?;
+    let trin_handle = run_trin_from_trin_config(trin_config).await?;
 
     tokio::signal::ctrl_c()
         .await
         .expect("failed to pause until ctrl-c");
 
-    if let Err(err) = rpc_handle.stop() {
+    if let Err(err) = trin_handle.rpc_server_handle.stop() {
         error!(err = %err, "Failed to close RPC server")
     }
 
diff --git a/bin/trin/src/run.rs b/bin/trin/src/run.rs
new file mode 100644
index 000000000..3f257e201
--- /dev/null
+++ b/bin/trin/src/run.rs
@@ -0,0 +1,273 @@
+use std::{net::SocketAddr, path::PathBuf, sync::Arc};
+
+use ethportal_api::{
+    types::{distance::Distance, network::Subnetwork},
+    utils::bytes::hex_encode,
+    version::get_trin_version,
+};
+use portalnet::{
+    config::PortalnetConfig,
+    discovery::{Discovery, Discv5UdpSocket},
+    events::PortalnetEvents,
+    utils::db::{configure_node_data_dir, configure_trin_data_dir},
+};
+use rpc::{config::RpcConfig, launch_jsonrpc_server, RpcServerHandle};
+use tokio::sync::{mpsc, RwLock};
+use tracing::info;
+use tree_hash::TreeHash;
+use trin_beacon::initialize_beacon_network;
+use trin_history::initialize_history_network;
+use trin_state::initialize_state_network;
+use trin_storage::{config::StorageCapacityConfig, PortalStorageConfigFactory};
+#[cfg(windows)]
+use trin_utils::cli::Web3TransportType;
+use trin_validation::oracle::HeaderOracle;
+use utp_rs::socket::UtpSocket;
+
+use crate::{
+    handle::{SubnetworkOverlays, TrinHandle},
+    TrinConfig,
+};
+
+pub struct NodeRuntimeConfig {
+    pub portal_subnetworks: Arc<Vec<Subnetwork>>,
+    pub max_radius: Distance,
+    pub enable_metrics_with_url: Option<SocketAddr>,
+    pub storage_capacity_config: StorageCapacityConfig,
+    pub node_data_dir: PathBuf,
+}
+
+/// Initializes the trin node with the provided configuration, returns TrinHandle
+pub async fn run_trin_from_trin_config(
+    trin_config: TrinConfig,
+) -> Result<TrinHandle, Box<dyn std::error::Error>> {
+    let trin_version = get_trin_version();
+    info!("Launching Trin: v{trin_version}");
+    info!(config = %trin_config, "With:");
+
+    // Setup temp trin data directory if we're in ephemeral mode
+    let trin_data_dir =
+        configure_trin_data_dir(trin_config.data_dir.clone(), trin_config.ephemeral)?;
+
+    // Configure node data dir based on the provided private key
+    let (node_data_dir, private_key) = configure_node_data_dir(
+        &trin_data_dir,
+        trin_config.private_key,
+        trin_config.network.network(),
+    )?;
+
+    let portalnet_config = trin_config.as_portalnet_config(private_key);
+    let node_runtime_config = trin_config.as_node_runtime_config(node_data_dir);
+    let rpc_config = RpcConfig::from(&trin_config);
+
+    run_trin_with_rpc(portalnet_config, node_runtime_config, rpc_config).await
+}
+
+/// Initializes the trin node with the provided configuration, returns SubnetworkOverlays
+///
+/// Useful for running Trin internally without the RPC server in other applications
+pub async fn run_trin(
+    portalnet_config: PortalnetConfig,
+    node_runtime_config: NodeRuntimeConfig,
+) -> Result<SubnetworkOverlays, Box<dyn std::error::Error>> {
+    let (subnetwork_overlays, _) =
+        run_trin_internal(portalnet_config, node_runtime_config, None).await?;
+    Ok(subnetwork_overlays)
+}
+
+/// Initializes the trin node with the provided configuration and RPC Server Config, returns
+/// TrinHandle
+///
+/// Useful for running Trin internally with the RPC server in other applications
+pub async fn run_trin_with_rpc(
+    portalnet_config: PortalnetConfig,
+    node_runtime_config: NodeRuntimeConfig,
+    rpc_config: RpcConfig,
+) -> Result<TrinHandle, Box<dyn std::error::Error>> {
+    let (subnetwork_overlays, rpc_server_handle) =
+        run_trin_internal(portalnet_config, node_runtime_config, Some(rpc_config)).await?;
+    let Some(rpc_server_handle) = rpc_server_handle else {
+        return Err("RPC server handle wasn't initialized".into());
+    };
+    Ok(TrinHandle {
+        subnetwork_overlays,
+        rpc_server_handle,
+    })
+}
+
+async fn run_trin_internal(
+    portalnet_config: PortalnetConfig,
+    node_runtime_config: NodeRuntimeConfig,
+    rpc_config: Option<RpcConfig>,
+) -> Result<(SubnetworkOverlays, Option<RpcServerHandle>), Box<dyn std::error::Error>> {
+    // Panic early on a windows build that is trying to use IPC, which is unsupported for now
+    // Make sure not to panic on non-windows configurations.
+    #[cfg(windows)]
+    if rpc_config
+        .as_ref()
+        .is_some_and(|rpc_config| matches!(rpc_config.web3_transport, Web3TransportType::IPC))
+    {
+        panic!("Tokio doesn't support Windows Unix Domain Sockets IPC, use --web3-transport http");
+    }
+
+    // Initialize base discovery protocol
+    let mut discovery = Discovery::new(portalnet_config.clone())?;
+    let talk_req_rx = discovery.start().await?;
+    let discovery = Arc::new(discovery);
+
+    // Initialize prometheus metrics
+    if let Some(addr) = node_runtime_config.enable_metrics_with_url {
+        prometheus_exporter::start(addr)?;
+    }
+
+    // Initialize validation oracle
+    let header_oracle = HeaderOracle::default();
+    info!(
+        hash_tree_root = %hex_encode(header_oracle.header_validator.pre_merge_acc.tree_hash_root().0),
+        "Loaded pre-merge accumulator."
+    );
+    let header_oracle = Arc::new(RwLock::new(header_oracle));
+
+    // Initialize and spawn uTP socket
+    let (utp_talk_reqs_tx, utp_talk_reqs_rx) = mpsc::unbounded_channel();
+
+    let discv5_utp_socket = Discv5UdpSocket::new(Arc::clone(&discovery), utp_talk_reqs_rx);
+    let utp_socket = UtpSocket::with_socket(discv5_utp_socket);
+    let utp_socket = Arc::new(utp_socket);
+
+    let storage_config_factory = PortalStorageConfigFactory::new(
+        node_runtime_config.storage_capacity_config,
+        discovery.local_enr().node_id(),
+        node_runtime_config.node_data_dir,
+    )?;
+
+    // Initialize state sub-network service and event handlers, if selected
+    let (state_handler, state_network_task, state_event_tx, state_jsonrpc_tx, state_event_stream) =
+        if node_runtime_config
+            .portal_subnetworks
+            .contains(&Subnetwork::State)
+        {
+            initialize_state_network(
+                &discovery,
+                utp_socket.clone(),
+                portalnet_config.clone(),
+                storage_config_factory
+                    .create(&Subnetwork::State, node_runtime_config.max_radius)?,
+                header_oracle.clone(),
+            )
+            .await?
+        } else {
+            (None, None, None, None, None)
+        };
+
+    // Initialize trin-beacon sub-network service and event handlers, if selected
+    let (
+        beacon_handler,
+        beacon_network_task,
+        beacon_event_tx,
+        beacon_jsonrpc_tx,
+        beacon_event_stream,
+    ) = if node_runtime_config
+        .portal_subnetworks
+        .contains(&Subnetwork::Beacon)
+    {
+        initialize_beacon_network(
+            &discovery,
+            utp_socket.clone(),
+            portalnet_config.clone(),
+            storage_config_factory.create(&Subnetwork::Beacon, Distance::MAX)?,
+            header_oracle.clone(),
+        )
+        .await?
+    } else {
+        (None, None, None, None, None)
+    };
+
+    // Initialize chain history sub-network service and event handlers, if selected
+    let (
+        history_handler,
+        history_network_task,
+        history_event_tx,
+        history_jsonrpc_tx,
+        history_event_stream,
+    ) = if node_runtime_config
+        .portal_subnetworks
+        .contains(&Subnetwork::History)
+    {
+        initialize_history_network(
+            &discovery,
+            utp_socket.clone(),
+            portalnet_config.clone(),
+            storage_config_factory.create(&Subnetwork::History, node_runtime_config.max_radius)?,
+            header_oracle.clone(),
+        )
+        .await?
+    } else {
+        (None, None, None, None, None)
+    };
+
+    // Launch JSON-RPC server
+    let rpc_server_handle = if let Some(rpc_config) = rpc_config {
+        let jsonrpc_discovery = Arc::clone(&discovery);
+        Some(
+            launch_jsonrpc_server(
+                rpc_config,
+                node_runtime_config.portal_subnetworks,
+                jsonrpc_discovery,
+                history_jsonrpc_tx,
+                state_jsonrpc_tx,
+                beacon_jsonrpc_tx,
+            )
+            .await?,
+        )
+    } else {
+        None
+    };
+
+    let subnetwork_overlays = SubnetworkOverlays {
+        history: history_handler
+            .as_ref()
+            .map(|handler| handler.network.clone()),
+        state: state_handler
+            .as_ref()
+            .map(|handler| handler.network.clone()),
+        beacon: beacon_handler
+            .as_ref()
+            .map(|handler| handler.network.clone()),
+    };
+
+    if let Some(handler) = state_handler {
+        tokio::spawn(async move { handler.handle_client_queries().await });
+    }
+    if let Some(handler) = history_handler {
+        tokio::spawn(async move { handler.handle_client_queries().await });
+    }
+    if let Some(handler) = beacon_handler {
+        tokio::spawn(async move { handler.handle_client_queries().await });
+    }
+
+    // Spawn main portal events handler
+    tokio::spawn(async move {
+        let events = PortalnetEvents::new(
+            talk_req_rx,
+            (history_event_tx, history_event_stream),
+            (state_event_tx, state_event_stream),
+            (beacon_event_tx, beacon_event_stream),
+            utp_talk_reqs_tx,
+        )
+        .await;
+        events.start().await;
+    });
+
+    if let Some(network) = history_network_task {
+        tokio::spawn(network);
+    }
+    if let Some(network) = state_network_task {
+        tokio::spawn(network);
+    }
+    if let Some(network) = beacon_network_task {
+        tokio::spawn(network);
+    }
+
+    Ok((subnetwork_overlays, rpc_server_handle))
+}
diff --git a/crates/rpc/src/config.rs b/crates/rpc/src/config.rs
index 7a1c1c76d..374957ae5 100644
--- a/crates/rpc/src/config.rs
+++ b/crates/rpc/src/config.rs
@@ -1,13 +1,11 @@
-use std::{path::PathBuf, sync::Arc};
+use std::path::PathBuf;
 
 use alloy::transports::http::reqwest::Url;
-use ethportal_api::types::network::Subnetwork;
 use trin_utils::cli::Web3TransportType;
 
 /// Configuration for the RPC server.
 #[derive(Clone)]
 pub struct RpcConfig {
-    pub portal_subnetworks: Arc<Vec<Subnetwork>>,
     pub web3_transport: Web3TransportType,
     pub web3_ipc_path: PathBuf,
     pub web3_http_address: Url,
diff --git a/crates/rpc/src/lib.rs b/crates/rpc/src/lib.rs
index 5e4da4bbd..f8ebdc768 100644
--- a/crates/rpc/src/lib.rs
+++ b/crates/rpc/src/lib.rs
@@ -48,6 +48,7 @@ use crate::{jsonrpsee::server::ServerBuilder, rpc_server::RpcServerConfig};
 
 pub async fn launch_jsonrpc_server(
     rpc_config: RpcConfig,
+    portal_subnetworks: Arc<Vec<Subnetwork>>,
     discv5: Arc<Discovery>,
     history_handler: Option<mpsc::UnboundedSender<HistoryJsonRpcRequest>>,
     state_handler: Option<mpsc::UnboundedSender<StateJsonRpcRequest>>,
@@ -56,7 +57,7 @@ pub async fn launch_jsonrpc_server(
     // Discv5 and Web3 modules are enabled with every network
     let mut modules = vec![PortalRpcModule::Discv5, PortalRpcModule::Web3];
 
-    for network in rpc_config.portal_subnetworks.iter() {
+    for network in portal_subnetworks.iter() {
         match network {
             Subnetwork::History => {
                 modules.push(PortalRpcModule::History);
diff --git a/crates/validation/src/oracle.rs b/crates/validation/src/oracle.rs
index 5e1ca2d0a..9638890f5 100644
--- a/crates/validation/src/oracle.rs
+++ b/crates/validation/src/oracle.rs
@@ -1,19 +1,19 @@
 use alloy::primitives::B256;
-use anyhow::anyhow;
-use enr::NodeId;
+use anyhow::{anyhow, bail};
 use ethportal_api::{
     consensus::header::BeaconBlockHeader,
     light_client::store::LightClientStore,
     types::{
         execution::header_with_proof::HeaderWithProof,
         jsonrpc::{
-            endpoints::{BeaconEndpoint, HistoryEndpoint, StateEndpoint},
+            endpoints::{BeaconEndpoint, HistoryEndpoint},
             request::{BeaconJsonRpcRequest, HistoryJsonRpcRequest, StateJsonRpcRequest},
         },
         portal::GetContentInfo,
     },
-    ContentValue, Enr, HistoryContentKey, HistoryContentValue,
+    ContentValue, HistoryContentKey, HistoryContentValue,
 };
+use serde::Deserialize;
 use serde_json::Value;
 use tokio::sync::mpsc;
 
@@ -42,36 +42,6 @@ impl HeaderOracle {
         }
     }
 
-    /// Returns the HeaderWithProof for the given block hash by performing a recursive find content
-    /// request.
-    pub async fn recursive_find_header_by_hash_with_proof(
-        &self,
-        block_hash: B256,
-    ) -> anyhow::Result<HeaderWithProof> {
-        let content_key = HistoryContentKey::new_block_header_by_hash(block_hash);
-        let endpoint = HistoryEndpoint::GetContent(content_key.clone());
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = HistoryJsonRpcRequest { endpoint, resp };
-        let tx = self.history_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let content = match resp_rx.recv().await {
-            Some(val) => {
-                val.map_err(|err| anyhow!("Chain history subnetwork request error: {err:?}"))?
-            }
-            None => return Err(anyhow!("No response from chain history subnetwork")),
-        };
-        let GetContentInfo { content, .. } = serde_json::from_value(content)?;
-        let content: HistoryContentValue = HistoryContentValue::decode(&content_key, &content)?;
-
-        match content {
-            HistoryContentValue::BlockHeaderWithProof(content) => Ok(content),
-            _ => Err(anyhow!(
-                "Invalid HistoryContentValue received from HeaderWithProof lookup, expected BlockHeaderWithProof: {content:?}"
-            )),
-        }
-    }
-
     pub fn history_jsonrpc_tx(
         &self,
     ) -> anyhow::Result<mpsc::UnboundedSender<HistoryJsonRpcRequest>> {
@@ -95,114 +65,74 @@ impl HeaderOracle {
         }
     }
 
-    pub async fn history_get_enr(
-        node_id: &NodeId,
-        history_jsonrpc_tx: mpsc::UnboundedSender<HistoryJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = HistoryEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = HistoryJsonRpcRequest { endpoint, resp };
-        history_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("History network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from History network")),
-        };
-
-        let enr: Enr = serde_json::from_value(enr_value)?;
-
-        Ok(enr)
-    }
-
-    pub async fn state_get_enr(
-        node_id: &NodeId,
-        state_jsonrpc_tx: mpsc::UnboundedSender<StateJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = StateEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = StateJsonRpcRequest { endpoint, resp };
-        state_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("State network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from State network")),
-        };
-
-        let enr: Enr = serde_json::from_value(enr_value)?;
-
-        Ok(enr)
-    }
-
-    pub async fn beacon_get_enr(
-        node_id: &NodeId,
-        beacon_jsonrpc_tx: mpsc::UnboundedSender<BeaconJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = BeaconEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        beacon_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
+    /// Returns the HeaderWithProof for the given block hash by performing a recursive find content
+    /// request.
+    pub async fn recursive_find_header_by_hash_with_proof(
+        &self,
+        block_hash: B256,
+    ) -> anyhow::Result<HeaderWithProof> {
+        let content_key = HistoryContentKey::new_block_header_by_hash(block_hash);
+        let endpoint = HistoryEndpoint::GetContent(content_key.clone());
 
-        let enr: Enr = serde_json::from_value(enr_value)?;
+        let GetContentInfo { content, .. } = self.send_history_request(endpoint).await?;
+        let content: HistoryContentValue = HistoryContentValue::decode(&content_key, &content)?;
 
-        Ok(enr)
+        match content {
+            HistoryContentValue::BlockHeaderWithProof(content) => Ok(content),
+            _ => Err(anyhow!(
+                "Invalid HistoryContentValue received from HeaderWithProof lookup, expected BlockHeaderWithProof: {content:?}"
+            )),
+        }
     }
 
     /// Return latest finalized root of the beacon state.
     pub async fn get_finalized_state_root(&self) -> anyhow::Result<B256> {
         let endpoint = BeaconEndpoint::FinalizedStateRoot;
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        let tx = self.beacon_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let state_root = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-
-        let state_root: B256 = serde_json::from_value(state_root)?;
-
-        Ok(state_root)
+        self.send_beacon_request(endpoint).await
     }
 
     /// Return latest finalized beacon header.
     pub async fn get_finalized_header(&self) -> anyhow::Result<BeaconBlockHeader> {
         let endpoint = BeaconEndpoint::FinalizedHeader;
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        let tx = self.beacon_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let header = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-
-        let header: BeaconBlockHeader = serde_json::from_value(header)?;
-
-        Ok(header)
+        self.send_beacon_request(endpoint).await
     }
 
     /// Return current light client store
     pub async fn get_light_client_store(&self) -> anyhow::Result<LightClientStore> {
         let endpoint = BeaconEndpoint::LightClientStore;
+        self.send_beacon_request(endpoint).await
+    }
+
+    async fn send_history_request<T: for<'de> Deserialize<'de>>(
+        &self,
+        endpoint: HistoryEndpoint,
+    ) -> anyhow::Result<T> {
+        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
+        let request = HistoryJsonRpcRequest { endpoint, resp };
+        let tx = self.history_jsonrpc_tx()?;
+        tx.send(request)?;
+
+        match resp_rx.recv().await {
+            Some(Ok(response)) => Ok(serde_json::from_value(response)?),
+            Some(Err(err)) => bail!("History network request error: {err:?}"),
+            None => bail!("No response from History network"),
+        }
+    }
+
+    async fn send_beacon_request<T: for<'de> Deserialize<'de>>(
+        &self,
+        endpoint: BeaconEndpoint,
+    ) -> anyhow::Result<T> {
         let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
         let request = BeaconJsonRpcRequest { endpoint, resp };
         let tx = self.beacon_jsonrpc_tx()?;
         tx.send(request)?;
 
-        let store = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-        let store: LightClientStore = serde_json::from_value(store)?;
-
-        Ok(store)
+        match resp_rx.recv().await {
+            Some(Ok(response)) => Ok(serde_json::from_value(response)?),
+            Some(Err(err)) => bail!("Beacon network request error: {err:?}"),
+            None => bail!("No response from Beacon network"),
+        }
     }
 }
 
diff --git a/docker/Dockerfile.bridge b/docker/Dockerfile.bridge
index 9c2ec4290..09f74782f 100644
--- a/docker/Dockerfile.bridge
+++ b/docker/Dockerfile.bridge
@@ -16,14 +16,13 @@ RUN cargo chef cook --release --recipe-path recipe.json
 # Build application
 # Copy over all project folders specified in the .dockerignore
 COPY . .
-RUN cargo build --release --locked -p trin -p portal-bridge
+RUN cargo build --release --locked -p portal-bridge
 
 # We do not need the Rust toolchain to run the binary!
 FROM ubuntu
 WORKDIR /app
 
 # copy build artifacts from build stage
-COPY --from=builder /app/target/release/trin /usr/bin/
 COPY --from=builder /app/target/release/portal-bridge /usr/bin/
 
 RUN apt-get update && apt-get install libcurl4 -y
diff --git a/test_assets/portalnet/beacon_bridge_data.yaml b/test_assets/portalnet/beacon_bridge_data.yaml
deleted file mode 100644
index ff3593e0d..000000000
--- a/test_assets/portalnet/beacon_bridge_data.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-# Test data for Beacon Portal Bridge
-
-# `LightClientUpdatesByRange` data, Slot Number: 6684738
-# https://github.com/ethereum/portal-network-specs/blob/c5f0a837e7ddf2a23956c4a71b2ed136256b095e/beacon-chain/beacon-network-test-vectors.md#lightclientupdatesbyrange
-- content_key: 0x1130030000000000000400000000000000
-  content_value: 0x10000000c16800007dd10000413a0100bba4da9640620000a02fcd95184de2d2e51bc4d160556c37f11e705440bae4d99a152d081b0c668ef64116481d8a1cb3f48196e1e36c073799e160cdbb10d253a3e14a16bc8e22f24458acf3d809aae7b9462533b70ea4952ba61c7e8cbb058a54c8e5be4de85c6f8883ea6bbc48894f21a06b72a110b32c25e805e9a693c1a40991c15094ba9830540d5dac8c618f87ca70d6c13bd22d84a1eef0952922fad56504efabe4e3b69fe522eb1aaa0c2b58ae4232cf81deb7a31036bc698b229df613f0babb92e6d18ba8b86ccd241ba4c6203a7ae14e9e4309acab9caaf4f3e860d0c1bcce89f65e4ad2df12a6f0c71f081910672d33c1114aa016c45828b42db508d66c781c9863c85b5187caff5c21b1bb65c42fc3955e1180a9bf49c471bca49e8660c3dd61c3878d1ddd95fdaa4b6308bbb3d235fd5a7380d4c4209bf625bed136f96f4e3750ac4e78030794fd26f32f8280ee8bcf64a2850c5c5bbbae51b02596560bb5cd2df0d699df530724ff44ad60c5566bfceda830d74471d82d921aa65d7c3f7414f3b9861371cc715f80656d06e0b6490db3f96e743db6b1354d23a39c9f614e9e72205c31ed1cc28f763524eefbc31b17d44db2dbc5d74ba8ec3fe6b5cb4e12d629f616de835c20aa7ad72f1d1ff03c9776bffaf555fe015623c2beaec8186aadb3d9a97df44b0959d4fe5b15521f490370ca61ae6b5a971660798aead1fc08285d03dd0fca7ce33742ae4c6ee121b8deb941a802fd8fd29323e4658b7f9c5625220e0e07ebf2220555ca9953e9208c36eef4a491b56bfc7e3dce6b8f84f5f98bbf64b1f5ce5712dbbd8579a294cf9e1448f7202b8803f8117ed23fbe561ed91ff3f1bc7f34349664544d6061a2d7a730b707b1552a115d79c79e9267a4cfc1240831f633c4ce50b6ac68408885d942423f846fa5e33555768af2d634c4c2543b4544a1f17a1c56b52db91a341695d5f6dbd430e0b4f44a2b8e782baf10aabe0300f1a283c4529c49cd84374d82ce23055099b76b3d5fdd3a0db2c517be48ad44a20fb948ba077052ddc92fe47f732317581b2c2af843f887d77e244b51d2d26d61a99827079061eea3aa0816427f0484b7262d0fa936d78f2c8881c8b385ba3d193f783a2792bffad5586263b5194ed9d6188c8dc90a2cd1f5c5807607c34a301ac551444d17003fa7fad4b49cc0ea209f98bf61062b826c39bb9ee484988adfe230a95d1f14887c48f0139cfa5104352db47aeffb555526f70841765d557026d22c3c39de331d93f1f2f7eeee28d70ec594848e4cbacdc253f2b3947def1f51a5fd359441b87f0307c541e75b76879b8387788397ca7c6e707a08efaa1dc531ea9c81b29ab01a5224f75d2786beb450a8049cc2ba8e04d53576177017fad0bd9f316daeabce7ae74007add71427d698e6fe880ec3a018d143c2cfd14913b10bfba77d4f8d988bd64a0e1af678227df22e9b67dd34b0254617e31326e06ff8e0362c988a5c6fa70155ceb2b945816b51d7270d54a4ad9acbc47dc4dd5595643c5152c8e413ea730d9ba31ea26c03666f0332a056690bab30b9edee92dc9c0ddc837db286370634ddcf2772142bf7161c2417fdb4c46de72e67d756c86eca1b9c79ca83462ceaad7cde0308f125d41ef4918bedf97c62b9d422645dbdbb91e9826bc0a2682a971170f605026ae4ddabb36f8a81f79aa612bb417be42f0465b37865f3484bfb3b0ff8c3a54f95f6e76e0d90f5c7a2aeb41e287a226da8a08c767e0c4e92506a20b94a34c0c9e93ea856b108911e748e0058d58984d69dee0040bcab4e4b38883bcd7762995ecf1822156e54bab46d29f718964222a1fcc22df2a6aa2d40cc82cf045dacb31504cf0c79f2bca9cc85e3b55c9dd93cc1dd90d75662c3eea0cf33f0b67d03ad92073b75dbdf7057edf9a4251ec13d4977b8786f1b86aa595e1a8fb1d4f35df6ebd6c0857f24e2bb8cb572059e676135bf49d778b16b6945ab69fd5cf8bb65cbe9b2a89f40e6f649431626231333d093fd1c2373ffd5c0b0afa376b5b8f71ab19877da4a49baeac594f2f3750bd2b72d72375c9fa82d265f1768ecaf268a02a2dc6ba4085ed8acfa94b158c7c0ef82d73e523e0bcb5f8538ae9192390faa6729179d33b6e89b367d6b51f96f694aa9e0a135b2afa1eb18d28d531e2d51d9bc4de29f07d874ee7d49ec8fffc540a6160f00041b73e48180cb53817c279ef2bb6f7635ce44a9a532a38a814a2f55c46da8461a877c7e734217e1a5ec3bac5e80b810be6a659684a04cd971ad470ef71a0c78566f94a4f2caafadcf5383fcd53c2efbdd4b39afc83dff21d36dd2ffa61cb868e2f307a433ab597e1ac8f3c8944de72249a2d34284bd59ad3ee335773381ca0cfa8526d0fecaf3f1499f037f74e2ddfdd75f2e5496132a8756a5625398a6f09be62348e320ccc49462d3edb5e795720d9581e9196154097251baba616b39173b58dd253eb43f0adae7253ffab765f0b4e0fdf26fed6358b8714880f253353a1395d05e1ee93e6782ab5c427084d77a39b142652ccf583063a176a03d43e67da347de182867eaada17e6e531da7c5321f07d27995301497999e44c80c1b8e4f43e7580caed6c12ed0d690254fa6c716e29ef9eb69d1d0948e8d71b66bb2b6a5409b54a0d6eb7230c4724430e14f68bd50fc86f0c89171d9369e0ebab6b3c61798aab5eb28076cb0a3e895c12afbc4c7af6ef696c86e30e371d9582eb4dd17c5f03c609b399c93419a0c9406cce61d52cb70dd6d636577e484714f3f18f6cc41369f2fce992187e4c8487874111bcd8926d5ce11cd3d79e425d82bec9cbce497edefcd5d4074c113b278af426fb75bfbf1630060f7fbc80c8c78ec32350d0c6ec5012813c935a2bd57c7c78e3f92a64f4b45db6c95635b48b17bdb59ac0a34bcdd702bdd0e738abc7ae91dbfb8878e1e471692341b9ea4da0f249c05ff89c3842d7fb0afd638ce15ac42794f7f625ec1066a21e5e20ecb8fb2b929f698184aa2b58c0ca2c11ea07b5c1c9f2ceca5a0d5d759c56f5a8c4ef1a9cead96aa3d858e2f17cb655807dd7442b0de2455eee6d5f3a0a4ab14d92a59c9442bd311370dbd9d616f8a6b1dc317a3764ce380e2818c62ff8fc1fcf16604f10e2c9367196ec7a9794275ee121651406e7feae5aa9affb5f23e7a58ce340a8a7066412e461931a071310695ee59769933feb86e3a4a4398274db1001bb2893a78cfc058f3583d4680c56829442bb4b150fc208cb6050478642650c2256550227b0e8e0a774bbb6f45308a9c3ca5bac64dbfc13dc8f723a2519a681320ad19862bd36b24f72cc9cd59c9c823fd372a7a36b353a1eea21e06ca7e149a06f786803021a11430c828cc3e7debb32e1cd1adc32105ef9a17e0baa289be7a7e73ea12fddf477aa6a4935767ed6285b5f22f5ee6e65e03247c341efbd489230abf1e82bc51c8b4a9d35f69039e04abeb0d908bd2501aaef7f70ade7f0f72a91b8228cd0b9a53abbf2cafd80335d03ccdea17aea88b9a90f5d84933f6fe779e7a70673a87555cc84102ac2f04cd705199675acaabb4616ef985a442f0e7918aa502509944d75cfcc0ed18645b4f2f1f51d92a2229b524ed9788dbc699f9cec1a8bd77b1b150a4247f82bcb01d1e217b2dc97db573e7b318924f4bdc8135e5c1eef9cf70464d5adc5ba03022e2750350d03290ef74ee46e1d60b04c620d91c5baa564f99341a53b5a3e3fbf420b6dd79ced99dbafb8ab464b281e763b5dee1ad61f34dedb0e84b0816ec21e5d41d9ea9e567f299e23a6f6ea978f45ab0d4ccce5c924ca25accc40ba7dff54c52f96a1d777804a31ef8e807e393110d189a4938587b1e85cca9975ffaf7e222d6a5d04f44bccac1fee3c340ab5d075b182915eace5e3dc087b36d8570bf6715bb952c63d9adedabe6fc29ba9da169286162d59109ff2dbef00824456ac6109032575ec4c1ac0bb446349b442149bd838455c7f1f49b2fac8b76117a0626b8fcfdf3a655d29a7019c18b05bcca0b2c094b7899c7d60d75be0b87bad28b31e4c2d5aaae016c2093930f3670860dc63248febfdebd8f47790a424f913d460f5c65d3033e579abb83d78cbe0dd7d1f17f1bd8ab2dfa22565ba39ce8a86df57a7f89c1f78e8017d326c3ccb61b159b86a2f8ab425cbfba7d2a05154fcc90fa5a372fcfa0b94cd292c1915a3d415adf437c07b1c94f42a965b82304b179db3335fac9f14538b4fab3f9e6c1399df9423fa16ff3b8e1356fc7dc9865027caf2f477733a525860c35502de873467f5c4cc85327594f985f00aa28c2608545b4f169347b54ac5e85c4ea90b5330fcead5862f025a93dc34161b2dda8ce0094091f21cc7e1ddc9ed4c9eafb4063d9e4524ac4a9b3ab124bdf1ef39bae7583713442460f4626f4513dae331305dc04ebae5b5b3ba8db650eac798f8ca4f4592e6832827b8a793eea6cd6bc88a8a524ff4caa2bad33cb34d689677de526b8103c31ba94c85dbd129ccf248a1ff8b352b1fd75ada2461ff2d67f88e23f92c8b76dc338ae5b9d049ea83b1a56d6f39767d50fb75fadfebb64f640f757ddfa59b1f774b034dd926af6fe17a95b88a534937429752a73c999ef9636151b542357216808738cdeeafc4977375f39cd10622ae77e92a0ba811ace515932babeb21903d0eab4c0352fd19d8c81dc4e3f63fb839a9c66f0a7533ce2c73bbeb6f38ace32e3fce208997f448aff2378e8d8b6e72821bc2a915e7138b8ca8b2b068892b541ec09fa55f0e991423f5dac5906d9c4f7ca711fab16f62eebdb63f5967785cd2a2d70c9ba96019a362aa2a826d737e376212b721f2b912dd0ab953342f2911698d70c98548b5927aadc3f26a730a2720cf355e5ba80eb1d588d5accbc8c0f9b768ef4c6c0093d852ee87f0d2a190bec647a07711e5ad1bf781a4b9e90b6aa4312ac799bea78c6d91d7f561b23e4eddc02066ea94d3a771e969147418f8001a4be459d0493aa1897faefbc4712278a590bb159deb222404bf459cd66c5258225b91f0e4a9b7450e380edb00a1cc9354b29fdc36f4bf76230ee0ceaed9799b5945ab72543bb5946605897a3135834de1c78e8b9f27a78e7eb2fb5db6f8a96c1ba32aa7e4e7126112935b8bea6608fb929f3a51ebc92d7de33afeb861ef0689c12d5f47528a48cd790f087e1da89d3d52a1975f47e84073f6b829bf165c0038f4a34925e931e89551c2c43c79dc399199ef1b3c3ced0a8a205536cd2a4e4e01d3883978aab681db88c5b9b02672d18b07d054cd47a9965bd3ddb672cea9b7f62d37712561ae3f903972f3c2a74702ec0426fd5cfd4972438bd3f418b9d22ac841b1c9ade100c9cf0b46809657119bd255b9e0763c3a540aaf5de61ef4618bfc78a0c3298bd44b6cf0f32783df4f3b5958027427030d2583bef3f7b6105aec9ac33e4f23fad8fe16385683fecdc2e957a1af4e9a3f3892122421870edc3d133929b138bf78494f74fdf7d7e76529f70f597e7619bf7cf8dc69fb0ce7c8f2dd8a9b50c02fb7fbdb0b533a7fecb14a3c3a91980d59aeb3f3a6eb0f000753051dc0d3d4060063ce408d2f025092e0495d0bac0e303e306a313f8a7dead7e2a09a58e91ba4e5ce2b3c06f4b4bca11fd322224e684c1b0ca9d38de4be8dd94974d0cfd4bb1e040d000c16f04291bd2b8e49b957c736dfdfa424cebf2d02677cee462924cd1e6516fa12e8cc118220678543c49f3a828e905b8e50f9f2d510626dceba0a256aa6a66e928d561bfc00fed0cfac979f95321ea7e5650107f09aa3b0ec68794f196b4252e7a33fb79bb669f2f6b85725cfb7b6347198f01ef8a8b68fdc159180e8e9dca4752575f8de301c53ce141212206fd416927974e2ed72be4ad6e84857f444c6b7a1bd475f5e0ce84c1d7f6de5b32ed201fa0b0888fa267efa725bc018f21c070cf6f77687e87dde53c16948d60bde2fc8903540afb8a0362beb5c1d4f243b9c625e6e4c0d13d63b66d6147b8fc10dd502e75b597b458fdef0f3386ea9e9dde040f23218f62b1e3ac328149f707904e70b11634c9d9b32a180ee2babb0daf43afe3d72366b125050ba99fa6a1bd5582ad1c591aedc31df1b94a480f35bca60c0a01fefcd464d20466a682b92ed81392f8d3c257dfc2f88f818f8083462f489b10f853d00474b85b487dcd638cb1ee279d5e10db3049d969e0c351346e7f65c5369234bcf94f71e9afaf06b874c0bda5faaf5f0631b180af5057aeabe207a10cf057fa750002fb0051a09a0ff11fcc9a27275f890f8cfa46f00b5c8fab9f0ce2f2b87f462cdfb8dbdcb709083f62adcc2f1535edbd5e195a6f0bfb12efac960bb071a98a4735104bedc4ec945103479ec5f554f4bcb27f44cc22393114cfdb351a7bea17e42acc1dd51c14c6140fa7b4097a6bbdbcb51fafb96008b4bec3971bc46f7cc2931cdc4dd8979be0b7c21ca413e35bdb4cdf18f77ffc5ce01a0b3f204d0106ecf93bd64b9f54208aad9386107f03c4cc0d079300c3ce1785ca7757e2f48669a4af624c9582c92615d86e42e214f05666a7bde242f48c4ea1a012ac3325f50e78db5ad7f309f46fcfaa49199888033698e9843c1e906b8c2c6bec6c3bff10445126534d208be4bd9917bae2bf7f7a60c56a34325895508115329a1bfa1e585b67b2f0a91f47eb6ae5695980dee1ae925797885c115a2b4fb62af17a6fddba58ec101d941bd8796233ed1337384a4599ed82b3d77408bdda9f57bfe1337955c5691ac71ff1e3e85ab3a9d7e071cc72b0b2518bf93796cff91a3434ebbccc89f23cd01ba1fa39e27f5e6c336b7c5e4aab254290f43dae16d0a11043f5416840fe8152fff6cb27aa7502f4b61426e0bc896bed04b8eb75c379c7d44f853a288d332c6d5527f6e4277e84aa8197648a711fe2f5f3e0f496f2cad4ecade603276d32c1edfdb9c7cb28ac2fa221a186162a18170198032f40c10cb7a970d9edf9128c0f64e6513b2b90696f48de91652fb168fc74782103fbaa65997987273d456fd85ad69543ac790306901638521b5f602ba4c17f4efd488c327e411e986b0b3b8961c3b8781395420103017503742f9da7c6751c7e536f1b3f8934e5ece5cc69e18b2bfc592e7d77e539ca8faecd9fe62a15e9eb09ee66859d83ea8f23b3b4f7bc75a2009720d353fe8f0fd771403b3fa3efe68c599a6682daade234f50289c71d7723c650ddcabfb7d8f56d589b3a92543548523dc5e65e10b7c1a9ece38c349d4d82010c2d87e61c8db8ea169ed196c5483fa21baad71664348c741c3befaaf492d6dde2970ed2ea9417871fbfe06fa029f5e574dade091c299283c5fec9f35515de79da0aa475e3e93018172dd6d552bf88878c2df4e3a5b40a8da682a717c9549f23fae8d1dbf71e840f1a4742c67e8f0afd9394fae2ea144bc46437001f269fdb0dd96967761e85e346b585427643bd3dc21123ca9d7372c84d0c35af7934a137c18206addb98f5085b20a755d7f8325fb56874144634b0bf2948e6b8b6b08c03ebe9c9cfb3e4cd3b0e42fed2ff85c9d6272d34f87a4740fbd48ba03008559be614d3f43a840a9669a97c461fc23ede8bd97f4f73473230dac2d3762a46b9f2bde6f34b37c11edc3426ea27f2d802604c0320280876ffb372e822195cab78f09cdd4d33be6c62004cb4a7738679febd1827b6a97ece3a1a39c7bb6f2947169bf7c4ecfb6c2ea7930be43cdf3e15332e51df8ddb959e6ea62b29289e4858838b4ad5513eea589d5e05e07c6c4a2bad5de7ba62382cc7cca95ffa9086558f1816d1f62d8201cfc1c8c2f69fb6abce44e3a5717db3e86c85b595f6b1794dc26fdd1b543df8e7d7b3a10b15e3e49ba48c28220d500754fdad3b0fd4deda34abe504428ccb32eefba7800487a7255563ea26f2f25da325e628acfaa6bbee7445f1082f688a0ba8ce54fc76a01a014a9d30518ad1bc63d6b8f1d8fbd62458366c8e93d2207353a84cfda30853ee4c38ffbe0f18431a27e19679d97772a6cd1d99bc3e3dfcbb1dbdbf4311ceff800bddf42cd3364bf3f2d15303aeea1f54852086ebe36e3127970c9f529cadcc3e085c764a00beb8eac187249cdb192ee5f8718a4ffde39ee4ed785e01b8fb3bcc214337de7f4444626893def8c090a8a9dd0e1ce370bf4ce923ec7e2287473c09b9ed0fbef868501ff8bc7418953cd57efcc4bb36bf9fc3559d9ef223b1f34dde87c9f8e27423a5b47bbd9a9df9665dd6d039ff541e9ae1a02343a7d19622f301b4e7f35a431f3b9ef02a0a8f10459c655eb7fb7ced2edc907961ec7949a8a72572830a4a53cfbe66b1e76417a84edeefb1c363191f34a8fc7d294cee87aac1bc976f31107327aa8b53a5e93864cc23f9e28bd36c8b9915b2b0eb1ff1887441da4200835cc552f5898cef63789fe596029f280fbf615496c894638e62ab4f573fe3837eb000be1b38598fb8e5b6ead0cd6ed4c33e4af93064ed6c4404c355397423d294cebca43032f1a45fc4c97efe0c5e7169f3d3b51aa8b43c9bed88480a9bf5bd6be442d52719608326a957b2c01743a61c319da07d7d38dfab7313f2a68990d7bec84861026b8ec16420abb969779137eb38f13c52eea6294020c2152e855821b836402b7f4746e023e67a72d249120c7b325b40e6083f1f8e528cbdfd4f823a71880567007f5b206456ad96be6975e7af8484b0c46b9ea111e6bbb1ce74d501b2f86767ec50c8860769939140ff6c80f4d4f1dcee5f2c45e92053600c1da27c27c4f686be53d93b7efaf78f6c5d02a06828c856cae0a485327ba1282cd184bec4911bd05ebac6821d52a83cc213259fab716974b9c55b284fd0f73ba77fea1b6414d1ffc3c0700cc60e90322bee7140e2f9eaec32994392fb7df3ef2f3447fc4bf6106f6dd2a38aacc29f3c6e3791d47e2238b652f72ded72d7b4f06ecc5b3bc5d84cb013f50ec1a33f5f258a700ec11d08cc237c1d2805a0285609990efef779818f21f61c1f0dadb682d69b64ab9c8bd47c614285a0efa3661b75bf02df5f1321fad07100f30835328bb8b7834ec22848cbc4b98c1023659ab471e4d1948fe3fc4620f41c1f75698a85ded3455d53549a676c1b357c7a9ea8f8def6c2cfc4a9e7e7e879c85e188687878fffa8641471fd131fcc02331fd4897ff6d34022fb5fad755b2a1354ad414f49a22041ac902592fe24aeb4e7ae13cdb0593768be42d80a41dcd757aadef357ed95d0cd4482e72960d2651d7355dc7e98f35ec0a25c17407a6d1fe05524e12c917b873f6d4a5d129cc0bff693e982dd9bfe4bfb450e4e2c88441ae88f39f29c5d1916ff4da3b7d7d042d75763cc0644acb698ddeec23ad1a6eb562dc23536b512462b26859c1e6b8222827498addecc085a014b79cc420523a28a2130549173b00a03b75e7963539f2be28b405d91cb72025b15539f003b6d55eb1dc0cea110765aeb74ada1ed163f91aca46cc5c011b41a8dfd800407efe23e6ddee32865e3bd64fa912baeaf344aad84f3af72b79e83c9c01b4d618a5b9cda07a48ff37928a3f6f7cf8d07769a3d863f1ef9a21d1a074ebe808bdc4842bae50cdeb7b7f68bffeaf387e56dc5cf2ef5ef3f9e552eb398802810502e0e3002e1172863df5f038ad950a673b255b17864f90e0a2f35e84dbb041dc3f1450036341772f3797dc6a0b711ac587755a58df3784812b541977adf4b8528da04f32f8d05749028391e8f23acb6c96f452fa359a5164609fc4b83306b1204e398352523efb616a2bba7e5136b26103cf99209e0a6b2a73b33d57128d881d9b4220b5853f7906258a8e6abd7c662d0f00bb82cb0a3902268a1a1e04bce389cd079ff1931bce834f256c1612ba793106a10ae8e58d331f66883a281b42a85880c202778e0ae285a31425dc263ba33070e5a58e5c361fafdbc148bf07a94cc0b85929693a0fc4656e0c2ad886329af66a4706ce2294fde79fbc3f69f22327e0c766021afbff1b57086f4d958c231de668b2973b714d6a9f75aed738040557f33298087fab2fae82cccecff47f5091a28724ad67a06e433da641f532a3ee19c10fd5c5494bc5af1ce5932dd8ebd675d4ea1332b2ca493aba40cacffbf9cbeb6365dcd8f5dae6b4668edd93972d7750420692690e15d0c96dd26158db08eac992c13ae782f1f19b1957451bdbb68239380618d0ffa9be5d5a22d7b214acd9f68bf6aa8740c0ee3b8c6a22809a20503b8cdee5cde4db5e01d8b38466a17977da2cfdbed2707b99a2a3a6ad5250996d91921524a2451da4251203472d38cd2f72304e7f08d2cbb812c86a52c9ce6488517b138f72b9ddd5ebb461a6b79a169e3572a376a3808f547bdbb877702832b441e0f386b13dbab529feb9fb55ff83291f9b79405c4148eea03aebc7a060fa7c6699ea7fc3423624e4bfb948dfa88e4c2dd5ca8f6113066ac3efed1e2ef6709317ac78a9c66b688039ee89e7c21509310f3848ad66c77897ce0ca86b92380ec3f7290bc218e6eb32f045317652f0f8e9983141a1d3b8d84d3fee52002ec2e4e9b6536a5c803175b811c795d33f6a3a7622fc7fa4024cea8bdc25bbf939a34133fc688fc1131695cf66eb77d76116007fa0d6013b446553501b601884675b69cde121814f62cefdc9a2a44a71bf4257a38a62c4fcc47e1008bbeab03bd3ecba7e8dc6b7cc26a23d5094efb4f97d1b943a2034ec9f5d71f3da2e3996f628aac72a662c74c8109996703894e0d8396c56e98fe5875e394a51cdd6c84805f81b3d41f312cc703af12fc55a79b179d19d587486b9df96e9fa46fba679d28248ca38a513bba7569f4dcded85065615fcaa042865b273828eec229efd7ce87a0a8e3847989e782cef966b3ef3edb7ddc04778690511a5c24c451c0251ce5ea0039afb04e4d44ed502ceecb1f039f008ca9a848185d67726734dc4d5f299baff17a43a01f3ddfb52fe5f22a7f4caefd3c96abbc8ed099ed93445e01510cea787e2640cea9ebc1c228948d2040c3359f24b7b20fa4843f02b5a6c93f3f2aa54a118893dce1b6a0b7a49841fce36a13f423c1ce19db228d15b8d097b1fdf23fda1b1002ea21f0c5980d921adcd1a044d28414b6c437254e55cbc98f97e60d07864b9efa5b8ee8100872dadd776010d97276e7ef91c1501a495cace101507df6f39bc48addbd80005cab6746126cb02dee3c79aea0da2c039c35111b715e8332634b4ba035e3bb6c2a1b5abc6349f8d8a9b542b506133cab0ea75f4b5a6c59f380caa9bc6efc580b515e664ea32fed5c2693b89e03b8150c6853ababe85d9990f17cdd8e3588ac8866816746154e309313a3766609dcf9704ce762e17e4c2e208c3a69a2f13230d7a9f5d9623ec568205e9b6ba872ad6ff2bd18b6ae8ede5773e7aface1c0f482cfd747459aebfe38035b09a0a77ddc93a446bca9fbf068bf24e5bce8aadff8c81054b8b76a47120169b1bbb979df664cbb7b446171121211709c7718c2c98ed0af217b0e8d00b1c7bbaf4f55ac65cc587ca0c26912b39609bb9b3374a791920af98390fe4f9d39960a8dcca29a8f5ab5011c570c89eea05d0ae1c24188539e693055c12edcf1f43e6f4bc69291e6a5785159a5198c64e7ab822315bfa11995a0ed94f9e821d0372cbc06a20bac2866a7f311253ca3314263cbb72183a9a395bcfa40bd7a3bd2476cdbc24dedea09024a97d22b3cd742fadd441d0b54abb3f9f45176cf799b337f83133a832328ef1683106efc19862a9d120e5e037cb1f4f35054b519c19fa04af2b793c030b3f60f0637124f82ac0017807c4272785b8f635ed5cd08b4d3fa1e71eb9e26eb17df7038fe8f1c708949c621d8c37208b2ee5866b080b1c6a043f36084f2335d93c43fdeb149aa60342f4ecbb12eb732570f3bd59caeb6efd36917e1a8152299995667da96d2752a2275e64c1033aa9f72115289c37656c5d0cc3da5126d5623e26209331572fb2504566d9884a0adfea13db397055dbe685be16a55ee7da1a0853a2f481ed422d52cb6497e1af59b3335558b3f10fdf7382af38102e76aeea6aa96a28bf4a752ea4614085725e4862640ea7826256078125603f88b0e5150782cc6644818063cf823fe12571647c1a394c874022913ea782a4da323b073ada87146c42ce9643611f88392536c84709d4abc1cf70bc8674cdbdb37430d737334929bf76a9bca76ec4876edd7c7139b63b4f07f7adc2f53e758842f7b223906ea08193522ab923a2b329ba0a2110e3dfbaa314f6fc635a0ceaac50a7c0c8bd83f5f100af1ec235f8a9d0af7a73550c0c0225e9b7df8ab484dba2808884938a0fd97a4008d7eafb1ce7ed35c69953dfb73a102638f58d63df06f703aa1e8fa68b1f8f5a4e91f44dad1f653b9473ad73173b0b642897278dd10bf2d627ef8f1041aeae096da73dda0d86bfe4e1a978f3cfd1633d7bdb8fe60990e7e8f5d59f90949a586dd6c4cf56cc020204a6f4fdb4567c4fa39600ca6cc162bf0e0ac458d55d20a815675550e6dc53924fde8e2d672889541d55ea74d099b250821c312fbeba27d7729f669bd073f10de7ab0cf1d11567bc416225e8ae4d0e06cc6159d485043a65e5625cb4088d7732c7a68daca19c74555934dbb837fc1f348f45cb1e246650760406e2d2b98d4e1a20a42daf52c67836a67c9e8859bd8f4901a273a67b3be4ae32efc7332fa8ba3f37587562733f7afb486cff7023287935a27467a654eb9ae2cce18a7103b352ecdeeb92b606930c91ae2a86a13ca51ceada5b9446591d63a14567ff435fc7197aec33880218c68a16b214c16e4d0fa4c85d3939bd40cb0b9bd7e49eef4dea32d6d40e29c2319156aa1b6eef6a4db95cd897b7ecc9210a9891360ca3cd272844c0f12c45d6c721a6ae69d7b75c7db652b27bd6aab7469b58d0261978f806a1c1ef3bf64a1f5049685144216e3def99256218396e1f62849f02d62f7d57ba804fcdcb3d3af241f28355fbb3cd35cbec44c1dbfab69831f9a8f22f8220e64f5d650a53950b61a40933db87269d4ee1327402325602e0f3c5e0e61420435b82360b651a98747562d64a048c3744a5f439e2afd11c5aecd62a162b1fefcd735bde8cb32624f35a51f2fcc033c0279010c4722ff3ded0167041dab5081c33fe1ddadc203747b35354e0ccb8dabf5596ddc1fea73e40a9effb19cee7e1b0e0ba727f2869dca820deb30c6995916458cff200aea1e8e01d845ac9e310d2ff5d1a639640882fd7f0ee60ca936419c6f49aecffefea7960a16b2204987397512e1aed2803984333061858ff63d935c1dca1c1244da88111296d42eba6593ec225560d289d055ea03feb93f2db35c363acc98d605e303fb0401cd76942216cc1acf4aea4e3676750e429f989763117af56fba9d11c23b4d616f1042d795606c1d4675c6d071e6c37676de2ca5505af3539cca8b7cc1105566c0218e51922c183538ddfbba1bdc94e14151baf7a6e8bd37d2dee1eecb5de0795d4a549bebebb074228b4865e36da1680a1f34e28fef99e45bd31e8822623c98bff8bfe48e8b7e502ddb362f7f0ae650ba7f026c134354cb00a8b4ee4f9256e61b0e9f10db9b17e27cd4698262316d4e6b2b5632b9bbd44c5835dd9b0c8fd7930a0ae5c1cb33c184f3a7f5f07d87a0a2e3891367c99cfab5444d21b91a82591c709837e7a4e2ed6f1637b0febbfc6596dcab6f37df82296ad68787ea878d8ceb82c973a1d6fa71971447f14d7ea0b1451565ef5d84f9f88596a04a028cce4ac442b404b571a658d57b8f1e3db934164bcd15600d078cc4b0dd12b0f1d0868396554dab4e99f48908621cd42932fa71827c63d17b5842e1ce159014b15a7ec09a7b369203ebd0fbaf539daefd7eea58718ab60b15a92edb36e3e5bd16e551c6f3add0a626c06dc0d0f12da97c0bc4e2bd284a0aaae21ac39a46bcaf1ecd6f20cc86e18223a62090c4b21af10ae396e30af277779c9317bd8017e4ba1f5585bb049f3c73b985d0bb5c64f2c02991fe1c0a21d048209433ec5bb94d7e5833457d38b403f8be4ec4fe0106b9a666f0db2753562713a0e53980ed6ede5d9e32dd998d64874abba665a040a3862214de712a40054a58db34b10d0f0c74995fe0319fde917f702dd29939b669f005d244ed23e5b22c1cb29163cf2cf927080c243d42637dd92cf97fc5b4c382729aec665a146c9c87fa3abb5bc5fdbd3a5eaef27d913e8a32b81f8e188f1871f4a8022ecbd4100c55a071adc41098f082220416fda91fd2a4a3db9bd8564db849b29bf4129f86aa41068e95b22a98b6e472710bdfdf66c7177ec74d241e78a4f5c97c21841506d88e01b36bf5979abf521d7837209aeed998847a8696f23825c8993ccf4da8e4667f262995f0a239bcc060b49f34eeeb32c4613f557143010bb8694d4d5c0d115054ca9fae9cb2491ff858798a069d9f37451323807c1d5b7e3b5468b8549195ad5fb9767bc8d1d0aafb4398774af6e7249817efab6e222a01ab0db1872d575ed6e6384980da95fd1b3b94b14b2179507ce37381ac5d2cd19416d14bd02d6e9e96123d22834bba5a90d3b9bbc4969b75aa049cf9d6cc454476fdd1c405d2648ecdb5ae7d799233d4b79727744226873a4c4314a5a4ded0162ea732105e13a1684f9d790696aebc53ff80d71fdfb1490fe2575c3509e19e6325945539a4439e7df7567e44ae1a4d5bf1d42356362fad6b1be59d4f85370657442ad06864d31eb1d1742fb56fe7618cbee0c3c620f065a98a86108e8a347e4dffa6dc4845f23a5e8ce744cb360a9e975b6ec55fa6ee979caeccd6f660ac36eb12cbd87621a7e4765562af6485b8631475f8332ba92086df0fb10465628d6d68e2aeea3b43b3349fcb9e4ea7680d751572376ff61e193df6d36a6a888267d586bd726a3c3ab419a1333f27ca86d838dc3b99364163389b3c03041d38fd23edda45e4a76535f1957b65bea88694c1abd78818c9966dd8546ea8af8ad807af8b74e798e3ac506b095c64f6d3f1b66267a873c45687eb0e2f75d24f00e38c03b25b658cd3ec5fe6d2cc15bcc86ef8a1d959b21b0a996e15ec8517731d61adc9a8c860e9e0790bddddf4d08587609886c06ac5a362175430fc84df1eb44e1ce697cca0628b2c7010b8cf00905065a80c742d0bb51b52d8e2bd677e0107f281022e1450a8e099354c5c933fda90762a064927ae53e16c4a63cf14403165c14edcf5d83b33ffeef76b495d94652be2a5be6336d83cf02a1acc388eb4cf483f6142fa46f60294aa98ad475b1cd11c4cd20c03a9903cd4abb82031116e968fee99fa1650a455f6d99579d9203138253712b4c6cef58ea1e1db5a059f6cd1a480a48f0f1edc1260e666330ab7327649b2b52d463a9f93627076abdc8497ae90053559f12237223d03c0e7dcb35da37a128549305836573f872da487309b7e093c819ea56eb394cfa2928610366d12a33a2353dfd26001353791ef9d7272bf6b48bacec642683f1e972bc20e4f9bacc01eb481a42efcd779e524e9a9f33e9dff975a50952659031918f5b4c87cd1a9d491b078473a9547ed692190609b6168f252987ed3439662878443762c324ef4afd79de1696fd96552f2f20628203d588b17980be2568d765d7b509894775ec05405a45dc4df4bf52149fcac97fdc0d1d9b55b310b9e6d44e3216f7eac5ae46a998c2f8947a2c63a22c4aacde07754321886a379eca135ada54d09a226dd57a5a089c3f6cfda9e93856d64e206d27faab6056989ad780ebfdf63b17986039f81e4b1b03b22e193c5f58d1327f2e6d50ddd0000b3ef67828c328a966e6e9d9c659bf104a32773ed252bc92fe5211b10ab869cb64292415902763bf1efbdccfbfdce50313ff70930703331cbbbfaa9484fa1ef4e66dddf5b68f1a4384a2155754633ccb6c43041cc8172b339b716d3eea560f16561af26e1ab6627d56746d5804054dd257b076d44a9b1c02cd7f1965dacd590ae6ef7523d288cdf1fe8af0e680741e280c7996fe8385f77daa7c563fd5d20123d2346891f361108825f47f45fb78197919eba711c2361e9ff28f309ff91fd2c46d097c8f32d815897d296f45681a5786a1cb9cb2b38da2b9e6722f409b9c2248c7e63a8f29b1825bd5a348031971a7cd04d3fd8f4b68b281101e1f69691512dbe1f29d2dfac606ecc6ec504fb0e2faa977c6bfce79a4a5f78cc84c05823e44eafadc03e0cac1710bbdf865939ce3692ff39a86ab7c17bc8a4a6faeabb66bc1ca30456c9f167724fb8bb51afbf9411bef7c1cbf64cb1fc901d928c4825e5c0d3d3629f98eaf8c442696987f90f4eaaaeb867c3487280769ded57fa17fd00ffac6eca879310bc76f8bf969baa4d0500a4bf93fbd4d565f2784d17e6090e209a96851b359d5f7a1aaabe20b8bc92658643f35a350a12b7bd1149fb166a35524bdeafc3d6667070083d483fe32bf5e3f0e3b92e3f85d1b43c90eb3bbad188fa243434cf2434e8c0d01b97bf560620d613b21baa429e7b236f0d74d7c247485f833d91c84e6083cab989e8189bfc1d6279a6a4772b452abd98769786bda8845efaaeee97e68b05eeeca9d53cf15f5ced17d794459b529d81109743908a0add5dea488841bd791287e8c013e0ff05e70472745b740693e5745d3390cdf3c0c5d89c34b82945f4b144fb25a09915eff80dafcd28933bc6e0b941b13382a4dade16ea7503bf4b32f878e16f42e68fb3d506bcc188ba8f17c99b1723597bf4e3926aaf6d9d08c114ad2329c6bb86c339267dbd4aedf7c5f88eb4f8ad24e52d4672502083a136087c294f85420d33b4fb75e884e9748058d617fbebc819adf0b2749a3e9a03a7ff519a994b473d0d2f6ac2535d688069968e491d68b934b27e91a355249b2b1999cfa2534b7cafb7adb7a333af7920ec7b628cc5725630c39462b967cb7bb1d562834b4c99ea6c54a7dde4a3a0f855540b8c17364b8f7691296909d34a116b0c5d12611b4b35ea9ea0e78cda73f28caca5985216b23eba02c2e9e755f29dd5316ab9e1f166efb0e3bb90aa93b5cc8ffef47b3bc703cc03db159d3c0c4bc782c6f951ba63b39e5da3533920a0522748f0c0d1b627ddf6c3db7eb10fa702a4905cabfa9078613b27c7c8c260c866faafe8019b34507f2e7c9b9a03b98bc2df51995e9f4d12a5f18fb3fd414cf8cee3870461589e59526fbd54a90c3760c4838b0740be6d74838dbcc1e850c96971f149776257de03ab53cd9a72ea0a7477027cd27eedf1277d417e19c48302b87d45a0cb98d7c7ac0e16d1bd06c3b73b8fd1225deb4f5148ce7ad3f7a20f815e099260cab984d031d93f8dd36e389f4a2d25aafd3f2feac1ffe23505f0893a15f6d7710030114b4cbac4c462e8afb0f7d06e70006178aaa83582da02b75cadab30cbb9bff792ec372de18d733788dac62ce7560d5aeb4718b59de6daaf1f7f098074ba273016344e56b4b6c602a23d8e2227a4d24bd3152eb8948b66896ec4d90d19ba14750e01c7a838c681a5cd547e8f0d60bc50a8ebbbe9b8e8376c1f89e332c395ff8f29ce0acac65e3028fc2f89e9fdc0cb5cb130c6247fb4ced171facb202ec0a1efe53764bb41802d7f883b12db55af6c03bd44a1fc8fe7310b5902a46b21826c5809b1dec4ca2e44e0b59bb3f7bf18a287bc32c56d73a328d5c5290c994c8c020978f440478e64bbabe5d1ee5260b42338c3a7e8f57c92f662c9162a6cb30fbbff7291a27c8a627958a717e55206873693b17cc62f9eaf7f35b106b70bffdb45045592ea09257d163d73e4fd276e6a6c7db3919167b1852444db4ae7e0a7a416fd2c04b902f2ebfcc7636a417a6e76b10fc4b4ee9cb28a7a9356060533876a7d2cec55a19a324b28a498b99a320eaf9c058e06e3b2ef9b041bab9c1c59b772f5c33cf3f7823754589bea3c5b83d0919be0b63bf1c956ff56fd3e2e54fa51b8a0f9817d26d7ec013b17b46ef0eb3bb4a5841c1ab4e09e9539459dfef60901e85cace2a4e9af6e19b271cdb576d941849cde94b4bc6c895ed590db92577a454577fcb2492aec26ca4df48a650b6252a69e7f43ed82ca920a81703e9f2f40a4b657ee49ebb9f7afc910f7b02fbeeaa55efae9525185af59350dff1e0a8a950d41cb506e5d0f130a25187e8a848df5a9ae0116073f53dbea8daf94ef017e619bc524b1f95a2a392beb57e364bfcc421e920c3cd959aec995e0e478435d66c397a0395f59f646da80035d589b1461da57abc197a9f1a900883c9c531a553124737455f6c09c519d1c700c456d2574cac092ac89408cad6acff72aaebb6c5aa625d0c68dd379ead27e40f0440bb41b44ed65d46ceaa7975778750ed65cb4fa5198b52b8e2c833428591561bf601c570645a01ea64ee6996822d7b7d32828e31a259a33d6f0c48b71d6a41b4e1007b72f3e958d323a43454683044cc01150bf805ca46e82d6a346eaa9a064d278a08f81c38324a1afbde7305739b14a21ff597699863aeff9cfb6d16304ac15d067a7a8db224dee7cd3657ecc89954c797774447547eeb3e12a9405dda59810327d0c4c9e8f4d7768093c1704a73ef3f0f1859beb132051cae9f28d9e26555f4f0eaefbabfbf37600e92e61fcc17e6a0616c765a08f92c5bbb926eef8eae80ca6f627804e749b8b77cdc281ece77ed49692288ee85a68242deefdbf86460f03bc0925abed8fef0ad0faf9b0f15512cf0bb80c2c7371a998e833fd244c6217d0b2006d818537ef661c916c89c32c126073669061b9a60c7db8fad2690d55efbb69392b9c6ce035f5efd7b4ad5a6b50e9fbb4837e38210a888fbf56b74ad5d19f38d2ea7cfd893d05de178c61242d665e23ff8951dda17983c932286a74a972bf088cc6b1917fcf024c2396ddbe1f3f414ecfd0042e8b573c01d4b9c5f39431a72dd88947382d55ea711ea01117918a8524be297ce9aa9a03d410486a2f03799428490251cab0e4cf0df6b423062e0662cb61807ffac3265ef27a7d364b8efc56981c86efd60fd9191662422c0ca86d96f721088379af7d72dd00854c1d2bbacf0ea8dbc1670f7d4a0392d9207d9c2877bf2b28839a612229edaca88d5a7461df1a1f21cb668de380a13af6bac56199d75e086ebf0ab561597fbf99d13a1a83af009c9fa6656973454f297b69684fd4550b3e3931c5a48a10c1ccb8e40c636f06e60ee77d8e6c7b3e633ba5db845ecfdcb4455171e79973d0949bb0e89338f588290097e063a541116e425ab70362886fa265b646612da2961e02fce36525cda6864c1a5bf191922984df3ae966e306778e710db11fb1c6ec9174179392f30080c40bbf845eb4715cdc54d89af5adbc8e1c8f1ab5d122fdc614aa9b21e8bd25a426619747b2a088205c45b70c34623b0cad96c8b51155a5530bc037c70d17f805f2c83171f80101d98c2c5dde182fe81806d5d0513e8ca626db0188a52049251a60c1cc04c91e326accfce227201b51a66d5532853e924cbd2465797f4bb1f521e6a04bb3e1b3c5b79eba5bf5855d634433880a1ac0552079971ae9c0a538ce9e321a227f42ab279313b764c87df889edc52c3b75bc816e2f145cf290be4de80a4b226a620348f36f0c249c15955ddca043701a983f13ca84a5a4b7f66734b9bdf8ece49c8894d4f75932dfea56d627faa709c7a4053c8b0a5e29e19d5316a95ce95ba4e3ace4ad0cfb09f6209365b220c50c94991ab45b8a25840d71e91a00a83d3e249c77f20d50812050a5d7bc7220304cc7d2d95b725dd0f7effe618a1e3d623cb0307282b864105b00fab12e8dd914e8ceec14a226bcb55e48298e3f98d89a8afac410aebb480e92a1f2ab759725a53cee1121b26516c7339c59e3d190c6aaa346ead9fa6f052a337a0dd93f891d5da9b418ed1a830f550503fd10554f613038804de0876bb65e9ab1e4a300c49251693adff74b8fc64a26de1b32e2eddffa40869488f384746124f88e222be84e35a534c945899b03471d8743f6018beee47502311986ba8f59a154ca0d88749fca4fbe30d3c58bad7e830d1b6c636fa91048c8ce48a2c8e9eaf646cbee938b17bb4842f85536094e72f662766f1445ad94a558e3fe334f0525b94b999521f4be3c5dcbcb4db266e1e2f941e6ebf299fecf814a207b4e8c03a65eef433f4d2598f2879d6e7e0b9a4ea480f25fb012e2efb5df292837a9eb21f2e69d396f9e00f9725d0975688b7c810502da275c308cc6e50c8bfc1361fde2cad9a59224c6663369d407d17f92cf8702a3dad2843e1f87702dceb029d99e19fb2af7b889887074ef3c0d759cb1a6735000e32a345697d5eb7322b29eb81c711ba560656ca3798c723a0f5234bc96e36804bbde0bcecbc461c6fbe52dba43ee98bab412c41bbd583d1df05b4ea1eb0a4acf11e5b29e6099d774f2bc5e5ad37a10baddfe37ebc350321ce07938a325323599fa4d7e1229fceee5f7f5d68bb67870c35d95742c878a40970f4f41c491c4c58980227dd28c2f4589298e90bd8acb7b1699b75c5da78f844557b282a995a28fa051687ad53fe76cc0667c76a143871d1b375ca3768ff8f25ab405611b50159d03a8a7e6cf8392337c4187908d9920825b0e28cb001020b8bb2a1dc5b58d7d17c716c24b2c2c43d02187e24a807396968dc0eaa4c3cd7459c2ba7186a35e7274bd7bc2b660c4b4471b93036bc13bce5a3959f2592b434ea4688c5f4d6c2c6c6cb0ead90614ebbb3a9b5d31b6a851660fcbbe5888e901d6e4f9195c4ed69d3a8f315d480be407a299afd33e0ac0ed46e63b5c266f7dc7eae464317a21a1fcad737aaeaeea3fd8693f7161732f9ed0dd3baeae1a985fd8e36f06cc56d66456e66d058bd1ad742ec62d5d4aa0d099ff3e023f38307652de335a0342918244cf8f52f08f3b5b32ea0b9edc9d9cf7c350ddf63dfff1fb4b001f2c7d5c86fb8c53937f0e663f981a07ff42440775f35c8bfc0d24c9c6e435ad4d2e65feb58c96a9ee381a0f90a203194bcf17b3e0d096d51a2e690862277aabdcacd11c31e4139882efe9119e28512390449c4a851b1fb48a6fe187f14b39a18823de494abbb80c831a395a1405fc1b1e1f5f223dc52a859057a745785d7ead17288bbb1f0c549d81a9e9b0ccb0122193023411286b86be3c70ec60f3ed24e433c24f1139fc627a8210b200a8f29ad03621ada70c329bc60e6544a86154ed033d278ec30d97a785b63b39bac14fada937ed96ef67e9535505da638007630d76a0eadea413a7b7eee9685da1b410f34fc64d8c658c50a1373b09f76cce409cdabc98dec2088229f823248bc475400a04d15d7f972e57ff0ac69d9720cb326ad620e945fbff919926a31d365afab2efbea9e6e6e6dbbd359f1ae61cd4f7ca020b89729bbcefdee36e1e075becb32a064e6fedfd7805ceb082a04f77d3314cd9dd65e5585262836259b6ad26f8b9ff50cfdb32af64c70c33dd1789753e58b6eebc792c54cad327b8371c06380a4d1c47eb8f8bbc671c0facb49bed681ef73e99ae13054188923907115cb6d9213d88189cba007be3d90bae1e452481e615c8fdefcdef640ce41bb12e618eb8e2598b579a03e620cb860c23e75dffa1fb3eadad7a2e79bb6f983aa906faab9916ac4039c4093525152fc206fc78d3944b3694ac460fbe8ee43e72aeb6f930a5c75890ba29ca99b5d72981b5d9dff12ec5bc73496e3c7be9b8777d33fb4816158515dc85f471d70c9bf3ebd2cd843c33eaa6a46e2bd7e0c000049babcd723e606e1f9473f604e4cb288203092bdbb8d111f31841d64e20cf02b13a50f623d3a76441f421325ecf01689b6d822b83034b5ffe85bcab7b756ae836668c7ab37ae6106c1bb34ca36c2d235ed896929a7534dc5f4f256af2a175887f6d81a5eb5162875d549619402d2a94e48d2a5805320563f72c0c72d9bc2ab4405f89569c2e3228d9de18a3895afdce1a9384349ac0410ae9e1060dbd42ad0d7306600f2f0317476fbd364a40dbe61e9946a6c88167a0516fa5763fab3140e9cdcaa3a1bb9cccca658304cc538bdc2051a2664ec649b7a2e5aa756c9d11234a608db6dc6db08676165a69788fde763d94fc9314030113aa9a2ff629ddc95514f184c7e7ce041afb295a17577409c9881554eab43528326af4545359b1f0d00dff1882890df40a536b7e95cfc14b77efce2102770f0b67fe29ae45d18985e19d105401533cbb0fa0bae576a7ac316a338dc2a50f4cdbe7ab037cc3d4053c2cb0a815e89b4d21e3dc339a2618f191fb5721e539976bc4fc6a3ec88e45d5981ff91673a61f06f16bc0aacb41b1cdab2f51fb31520389910599766002505164028b2fad528f695eeb35cc09ef6fc9c185ccc67185c6d62884199e80aefa63e9ba4f3383863603d2586be5b3c7b84a6846e2f02700c64b8f2c70e2f6f3a2c4124fa28c66b0337125853defca8376a2fae96b9c9f919eb762dc4af1abbe5ea21555f6c24c0f4731179d302276189055b593ef9ec686b2e67e5244027bc2d220298bf53b2d608121e3f4efea1e5fbb0c9746b79cd29a2f2d804b7e0470e6747ae0005031c68572f01caea800097e29474454ecaabeebb9d0414a69a166e3d1e5f86fdacf7331ddf3c10b38bd8b6fcc27cb792ed75da6d686172e7fd8e34df13378435fd04f5660998d2e65ffd41f51897e4badb5887b7a3477cf0566251f44b52abfc8de64ad1b7b0794e7aa935211d91180a60a540e65ad5001d8144664852401a44fa1c6673a6eb3508b222bba8f781d9cd86a6eb38923b9a1e6cfce80ac32428f6539805ecb578901fa8bf311bae2f6b311104cc548b085ee5ef217da8fc5d13c43ba6d98aa88d8654a0b1e5a579ba6230e50e4a176d38b5328151ed4c962a9a3ada05202fee23fae5a9b35707d8cb226d81699abfc545d99cb1e87993b15e0ccfd4cbdca6dab24209f060bd6dbd85c0f8614c651959bc3dafabfa2f09a6809c5bfe17b8ab7b244ffe8feac3d3122f91166cd976ffb6f23834af19f79a9fd5982af4879ccc6a38af50af199a471d55d83a72cd78b42aa7f621bafeae4532c9ee7f9fe82924671dd4875276c847d4eb3dbe8784298acc16656da77f2a02e872b5cf6c8b6a2ea530b38871f697a456c63bcd21d6a2951465c065ce7d8dd2a42f3637903306833d05aae8820e016b04723fc58781797d3c582b8342b63e82b2689a80465ca2dd116ecc4a3701bf3cccb00558f93236bed42ed0b7c8fad10db6245e9d7eb018cb8edd2658d56ee88345cd7ecd52515024771057fd4362b83ba8b10cb70ed0b297c8afd8df8b4d643bebe4d2066b40e867e730e28bccf5fd910b3697f52495ff972ca6e73b68993566c228c5b5cb5f8dc7bc4679368adc15c1222e04c4e13d2b6a7324dbaac041590d49295e0fd4506e5c9ba921e69720c08ec259f2a3649bb36937be07732f821ce1b7fed7a90cb10866021c77f836cc34b3e4d1433da1aa80db378ccb1352b8df90a3ba3ee57330ab5d3c0faee8ecfd74289944f6f8d4cbe95445c6c193ac3c4f124c9133bc27424d6809618903f361cea28c3d356c59669d9d0a673d2817a5a3a0053e757c5b294933dd9c3da1266630af4785f7c53f581a3e8ea8eff8ff01636da7e2664bad7b26a6e11cb8d53fe14fff1050e722af94b8c9e9a48b61766b78537ac0ff8d6bacfe1fc0d10cab7408abf1c6086a2a491c3933d0ae0d81c4dbf0905444dbc96d18e92b29cfc68a50ffaff0b69f54427928034b2e7b025a200798a706b1687ec745ac34244cde2598a24f85e11c604748f458caadbaf7a911404d97e63240139ff6a5d5d4a83554b736c0b3684a6cf9ff6f815f82f9083c25752498d248971fc19428187400373e24027e1348e5191f465133a798674ea682ea8e75e861848ed54839db38888306a3dea5d91d4a7859ec73480bcf50df032dd37151371710e72711d2dddc1cd47e4119ff551e3b5a4cc67c692967f42fb3ab2d782e10ab436982b7398dba6026f6ebc8326711de7e9fffd9b11f48793d6ecb08abd8e2b2175ca825c0dc2db7ce1d3b2e77c214ef829eba0fb82f05df4d2b335d923d9e475f567d93e62c3dece08636c5d8979b6fd62690b49e30f00df4f657602cdc534f80b7f0316a51ec94d76debfa60ea319890f2e1bd6c7817a80c83bf74ba6cf55b9bc77db5f0462e242ed63091dd6e109c19282d0bf99a717f5330a8a22fb0925163187c80ebac059e1f5c830a85e65fe07fc230e8861b9e68228ff568dcb4f53938e8af787905697337618311387f22becd4d3ffc69356d3e7f771a4ef3bd1d99ceb4bc0d0cf5b959820fc7b68c45545979535fa51b1161643d5e86b8a133846a15fb1071ccf38d41f1322e0bb6fa464534949056a8c3bf257e6170e55f66ff1a594b5d3aca666924f91a4ac1f4ef7b478ccef97e6628d444027a9e7782b7a240f24d1e19ea2fd216256f56b13d733bf05c68921b0af9ff1474ba17b983af47b249d86342be4a4be19d9fb266e0412cf0d95795cf6b2ff8a25b39744c4241f4caf156566d7b3df45f58779319e4652c237b6fd1bd6ab723ffbeba0ad1edc911cc1b21689d49341fb0b9d25b46aec4a2675e7e88ff283559c646ecc812a2741f718c4550f799255cb3a9c4c6df4365e725135623a9f1d550d750a35b35ba7eaab9a086a60daaff39df4409eadd6377c1dec954f95002e9002658eb31414a132606c5aa5a4d1071fd3a52975d0afec7da0057e23ea82989a73e0eb18f4d1a13d94549c7364e36d1e8f5a72feeee1e4934fe75b649f28fbd43b3cdc5b3c3b001959baed2cdda08efbfc3a09155cd784825d2e6fe4721fd69a1d736c36333361e5567243db7a3cd33c98afd079334477cb03603f4f9084944ac22f7540550eddbb7bbed6fa4570b52d0e10d46b1a633e1528f5fc6669e9c3ecd8a5ef415b5bb1a2401fdbdf45d1aba65ba24182e3a8a3a57aaa8cf9e66d2a8a34628332605c787592edca384a419ef7d589f492694ce39473def05381d5a6cff673718360207cff45e82d88046c79710094363e419ca037138dd09bf956ed9b02f7b718d92f6cc0fa03c13d13f3a0bf9b86d1cf2d091ce1a2c319a28cc2d178dfcff1d51bf8e96376aa936ddfa8ec0589f9cb3fcd6103704ba982c1ff428e426921b2b28ed5a3e65f239a4196cd1edd8d0e1702cd1ebe72a434545fa8710b9965c893ec4fcfefbbd4aa0c9c113f91368014ea0827edd4638a2b25c7b87c2c4bd84a62f205c1cd56e451aceb2e4acfd065e2776da244b44168d2e0de3e4998f4a93fe6f3cfaf9014f45cb4c945a8d669bb04f58c0b10bfe4b700733d8d78e6206d3de506ec06dcdcda7b6ce88770ac0579d8091e5273a6c2fdf39622e39effe80dec5fc74ff1e07283092da236687b0b9abc810d707a1d4a78712ac2c5e3af4eb51e497e60578102c67e9189c3b3ac276e096c8338ceda417020b80c56f633b6154c38df7467260aa4a09fc44e8c83f7cf9174a60704e57aab34397bdabc7b01c4ccf18a36d1c7e53ea5daec2039396a32be0966ce09c1294750b70c7bb6a79fcb73174bf7e37e1e0aed18d1977efd5e40a529eb47f9a5687b57e8ed25a64e0971a3df7b89187f510687fddd3b5babd2675a63983081e687a4ed4fe3cfa67195bac2f409458ede7291c435e4861466d03926c69cc3e21092e2759b62f9e18ac1fd3c7bde671e2efae4138476027cac131c846e650c9a8d0a866f35db101ff93465b5d3196850994c4204ab3e6fbaa02231b57249f4c2f7d8987e34d5835f455bc9e02f6a97f5494e1c5f5ecf2e2fbe481b63315063b7b64d65b836886f03afad6d1c1af0ec06f49eaf8776f8fb343e6094e50ebdc2292921116ef05f079e2f99ad31bf0b807606ab48abe4ae3e48a963d7d8b5e402564da2cdc47293e303ccc47d5ad658724a0d8c0a2c3695fb5b71f87a5025df6850b7b2e853eb05eb60a307ca25dcbd29808e51f7d10e0a6a43b3c6b0a660718060669008fd89e3f33b1bfc3b406a6c2c009240129b147f7ffd8f622463489aaced98989077b0b6b2949c7fdaa9f65db9c89c70af403d55c381b336f695782969c95d6787c8c165d975808d3c85242b62173ae19019bc735c1e5908a42851ce905f8130d0deca77eff4efa4869a89e9d9cb1ba21759234104e984036d528ef0ef51632feb85e37af26d263015ebbfce15ab81aba53e109acba5a14ea6a68f387baa3c95af6d355b0e678fc58d25df71048d9226e20026c722c97e3d1e8e473c94163d66a1b715e69865ed4c11a97f2574e8b6dd603d22231064b35404f8def2a019196ab6d0e8270b7e325369351510634150086f67945be2519616a001ccc9457bbcd6b38c6d3a9e0f875f9c1358e021c0df0d75d8d90cb2878e6eaba784a357a35bca2032225dc63a5ab707eeeb3a68c5479dc8e19165c81aa82edc8ff174d91a5c195a778aa265f35a4b7adb596caeddb566d86b15b4ad446ebc4a7c34889d0f69e6b820ae5ee2d1af24d3119da615aadb269acf4b52d51ea661a810cb61fad7e0320bc2954373d0829a31594bc99a2aaf640759aa6f6ab6afd524a29a4e10836398a91aab273a2d70ce4f1e6f1d5b7a135197b578caa79f3446d1a69e362c850a59d2dcec90907b88bd4c55b5e966849688709cca66bb4ec87ddbc13e763d2b6876ab66a39a381b05e81ebd67d981b5bc036b802fd129e1a68d349e0d6cf660c210298bc40ddee173b376edac7e977e029ed8552ea14c253bc3825855775653fc19af17fc74c6e98d85a6f5c2e07852dd641adbfb7c6b3aeee07da82d59a4fffd6d3a47524cb657369ce1ef819c449864c5ebb288f42dfc8fb2a298af5995ead97163836df7a97abe11fbee7e0baae774557b395d8b623b1f1ec1018327533e38f216f6c3cc44b28ac415ebb425720374f082c1f07a55c33186370c5592a63d47b74ead85d6689a2cf115fd1b276730fa141465f13b6f8aa00a6c59f7c889f7d5f5e5e4047646e360e88184f8edf765c6a7c1022de11cf54b09ab7a3118d6508ec96f4fc96b21618390e680311a13932924f5831629f334cbdd0bc92974300e997a210c8c258e164298526666c79b17123d501ee0fb7857a5d374e4957afe58a8faff3a13b796d15dd5c3199fca2025e2933c9ea5fafd3b58b8ff5714ed82babcd182663041a07c94504a8eb3ea24d387c1ba69fcd89f8eeae705d119aa53cb09676af6e1c9f87b429ef5d95c2abf7fdb48d68962b48fab9286febbcf7e82169866c555f8729272f217226fa26e853a9ef7562cd1d2dd6ad688370d848ba4b67b0efccae7becef78840386f6bcfdac20d2337e80adbb871a60ae6d666c091ed5df6930b0cfd9f460d2dcf40d91a5cc870e615b4956457f6af14b88e7dec7513d24d0167a277d2acd0c17b3fa23d524396e0396a499ec10436d9760c2a10b13690eaf144a6792e3f8c58c905a52dbd8c5b2a915a7d53a901e9e4ab69879faebea0d5e6a0c93b0ba582d990f4b37691e71fa7eecff2f46d6eb038cbbc6aebeef7e3c93a30a162b6fc013459afad7403915981fca67d6dc351c6d95ecef7327b1b42d24fb12063b239b21458810bf2e180feefd51bdbb0206050243313bd351d3fb5cc973137b0f8d1fdbdfe7aa2676ac7e1ab4c2d025b93abb8192aadb8aee09cbc0bccf21ba0ce528d30eb02282624483451aee0c9f3c78067f73263ac8d6a682a661d5ca6caf3d098fc10f69e9638cde29cf3910c91edcf7997ddca9ad4f5ab9f3e532889e2aa9d2f0a0cc25bd3023da0ec2a250ae3dfea81e6170d219b353a92134d325ade1b1c1b0703cfc8c4850cc4d86b17d7578a3bb238c84381f0d22bea80d1aa011131e68f19c65cb1e4bc624007b5447e27663b597d5dc8b5f8a65b9717eeaa16db01d9ae46f4403cbcda7d93913f95231f1179aba3c8eb2ec4d3afcaa5319bd28600ef4310ee0fc07c37eb7486c10b4646cc34b65556ba6ad2df755377c2ec030d08618db4c16390c02706ffb4091f5f7eeea71be8a0bccaf111b31e28dec0aef684167ce60157cd2f5c6ec681e1bb3be6e26fb2ad50db4c6af4555956e7d77260ddf77c66a1921ebac223801dc08209136c8f7f4b3eb7ae4c6c51328908179bcd1908a8c9367f6a624053467a4a529731d65fce6c0f58ff41ecfc863f4d6afd468f73a8ac6165f9ec0b81181703b5582e94e8aae699aa94206687e9a7bb99b2840c12cf7656459a75006f0eb3a851cfe1000ad2be3e05ef8e3ebe3ab2faec7b305b598c90577ab411dcdfb704dce0b4e4f6694e88895904f8100cc34c7787aadd4f98f2fd9def3e34dcde213adebae78403609312cb50c0bd11e5851132a0f0de633b3cd39b92c05ca2ec4d6ee506d67f5d5d6ff28b6b40cdf0580f079c7b3096077c8ce1e0204fdbd5e4eac8aae821b2e3fe61618a74299263a5ab0fd29e7255084144c3419f9adb5434578594fc5fb772cfb79be7030fe71b997b858083ed760c228f6cb4928fb3438822037da8f4712f9243de262adfb3a4364293bd50fb5470e488705695d4ab4b5e9edb9b64c8b69665cc68c42c8c3dc82875ba93d87c83dce83e6428af1abe244f540e4c89d0f00b2b86c79618401e30da0323c985f1f5e4ee788bcab3223e403be1af41c06d46266eb272c2be2ba5c0890ba77e04cc89a6488a900ab8a7a976dcd7a7382e36cd99aee74c6870c192c0832b4c4af1e644c11d23c4b1bd04632869cc8bfe415210b18180c266482f66662268b32ec2ea20bffe50127ca1ecf1db0ad1838acbeb91dff4e9186659a06ef70a41a85d1b3871c8be9262ea330d7c6e18f6a7870beae99e302e0a036fe9e3928c7f09648b18ef15bd6ff626d28639b6b6fd808b7536d36af7ac8a0b63c59163b2d65015f89d2e06657bd19a19927e3747c48209bec02078fb1d4e450e128cdc1dd14f570d13ea3958a19782fc3cd03ac74f52d03e9fd5551fc1d9ced4ebc29ff0b863c6989ee7d9661c3653700d01673dcfd504541b2aa8cd91e49a005ae270d5d1170abda56daa1004dea9a328630eee4695d40f83866e0e9ad5af4b14edca1ddc5d210e9dbb2a6e89d94b0754a23cd7671893a694ef2b63fd5be1fb918aab341d7e4eb5703fd04faa19627cf42df97f8e1730b9d7a444e8a64acf0a13de591767840ec39142e7e4e6ddaafa3c5d7fc0857a0a5370e89df339b23ffdd9b209c63430b68be69e375eadf9961c14056948dde9acee947fad1bda78de64180a92143ff4ddf8d90d38d1af41512b5c754430d84a0fa11f87356b95b1bc94615e7c0ae2da005e86529d6ad2255c43e8fb7fc7f0e4888132784b6e6750072dea3710705bab05b71c2a5d5fb567cebf4da4422cd27118eab5ab83badf2e31621fd74e899ea8583205e6e48c5ed0a32bf329ef9d3b91fd617ce4e51080c0c4ac8062ff2b74edeacd6a5a8130fbb19cb379cc30a84be52c0e692f2c3e061762e393c66f0677e553201669eeb28ecc54df42e1066614a9ff398c69905c485e937df258a28df3c5c5bc50953b8594b3d6a01396354627bb665c222b5b378c5af92db1eb29757eabfb31bd8961ba06ddad6d4d3b2cd74a5747f19438482f4ccee0d7549259283d239e3495e01586b5ca8b77ee2302bebf9051c71fecba9603c3aad39b239e000edb45f3b163110499995270b78c7c518ffa892a9b4886b59951f7d7576f3d58c84f950fb0c08e283b167d8b357a09c5efffddad9e6d00f1cd24b07c1f44a417bb323ef0760b0252aa34a5535484378f64729669db6b95123eabc91d70ebe1014cecd378ccc4575ad74dd49d312a403a3aca101b571e05e4835840c116a09b312490ca24a8765f1428e348d769c750a56779ce5a9706014c894b0ccb2b010ef84fafc03fea0fbb528080736d5a680d39b3812baaa39253f0a99ee71188486bd76d0351bbb62b3bd8fede8fce6a3a2ea4365aa1dca54fad038a91b0417e6b1a48c747af5a1b84865c20dd4ee1656a243fdad1e08fe9323e96c98266e6526fc282aa455720aa6b8d14adeee325a41c4ca4c626978d6ac24fac9648a48b96e63832e72bee3dbd60a4ac58b6f49d2d3e703f7da9dacc365bd2a789d3681b645d861e6c744a15c1b8f06fa44598c9bea97ef71886f83738bf2d098f4c0437e0034bf2f55522614a38a6f3b668e41c712a2abf93cb781fa53c7b16f87856c06719b946fbbff605cf571ce7df0ebfb91c49d5483be7d2a0437bc4c085fc79112e8621153ac5bb20ddedec8ec6c3d9290ba43a8299c79d89e384c55983a86d04e8ba52ecaca9cb65dc95705c9733acb92d01944ca807fc3bebca9771f0523384ab23f9791df8296e2c44a03adb4eb8f88d53d6a886c166bf17c2d30784674db11d42ed3900458133c6dc0f9a5613e7e5a78d3c42a15397166df8797a8a7b8c0d195e21f979e1921cf47636779548f5dc7a2e9a21fe33ec0ff6afdc6be097c3a3f02321e6d66d3883c1f9608a0702fa20490050f82d37703c58ced685b4b1f0bef920f96a6fcfa7810fefba487546b928d2c59ac8cb364059624ba1ce2de1c742a6ef5452cedee3e0f8e7cb1ead2c33a81e058bab9c06c32ecc0537ce874cf90af714db6918c5f224fd9bd9a2ffe5186cdb56458ec13500ec628a89a1a92d23535464ea59fa4887e6ab8a77de41e02d66206ded7838f2cc469f13bc532435d59fc631936ccc17dd64981286a094ae5bbf695a9cf5fd2384b7007abf5f44306d19e8890211d23b3eb3433ecd3df91032020d76c6e31dc8bd9e2c679f7a9900ddda35b6f6bfb0c64c68aeed8559dc223222a3860538d61cabcb633b7d0754322e70e04543738129b39e13edd7a7b261a329be0a5d9f8adb76a121461a123f8a739e469b804651a24f7194c00349c1a040407508be2aa0f4bff04b39dd39942ec35e889536de2aa585035883157cffe293eb149089766ad96a4a0f57af7d5384197c53877503345337e97b197bcd951767a86c6535bb47161058f9a331d487dd0065ef0d24823ac1b65dc0ef98610fb9f41020816ceb1be08078d7278ed4abaceb6fc3b794bdc71a7a574f32ede716cadbbc4b179578eda1e7a6005f66ffbadbd8e99d9f684ccf479eb60485fdf5b6cc3be747b65a44c68f9e59603881adc31128b62f1b32531aa96f8deb25f27cc21619f99a64e71f92f096e0255acc42a52062cc90ccbf9403912260fce0c3532d8966749d5245ea1bdce2b2e326f97322707fea0ac3eca59f02757fe3085dc0b55bf3679543f0ed7a13fd0286b39b4f938b5e7be98c0250cf1a65dcbcb27f06ff3176727e9075aac7088d3be86fc9ac84d223b89f96d3f929cc83adac2f79e372e5000e4ac5cf07531d26af2270c6caa5c1bf880264672b27333fdbb45398288702d7845a39f910fea972e41232bed4686f5f4808a695976b944be82824bbde5a82df0459f361eba52db16e5efb723db95326e89dec8c13ff4119e72bef2e2d48227d8ed0077084700d0a136443dd0d86b2c9c327feb1abcadc2f6d2f319b8aa5ba3c3ba327d7600b5c3ac6f4b14e5b4273c1a6d2bab4e2bd52ddcf5767866420f465e7f56b63e6e0e50d7b8937952485c8331b5757a4e5a84fe3f0d6fc85b95d182c4aac820095227706a2693d17faff900a494b6d640f1474b55bd92b733ab20a3cd2e299584030a7e07f64f6b1332757c960b5c5a02e3e4799c6de0d671407285d44ef5ca4be8ab042511af0afa7b4b7fe82421003e28c5aef6c27bd1555652b17910914439166d2729d87251d94977c97ba4f2433a9f163e120e55b64dbaf4bc9bccc578aaf732c3007eafa8d75507721e4f440185d8e632ecec13ed7c71ad9aa5e92161cdd92c9f6c1c8dced968454eca88284e8e2773c8ad5abeabcbe1a75b153f52f52a283b0cf2b3a1a3cf6545cf3b35dee4ade155b613a4b123ddcaec6a9e987f7bdfa772a985040651bb670cfd342577e50d2cd9ba618b4a6d70a21053a57de473eba8c3d78172272460fa35ab033069108063055641771102ac0b0c5cdde74946fada228a7b963ce3e675b8f48d1f1ea6a07d1ca4614d3bd13d1966e068c4bc29c709e9672012e78ce71facd3ba40e61a40607ac1b00105173b974d526f7f898ff9f30038630005ed29fb8d09cf8ac88bbb6ce0b0250edd959bb4ce4c54abcbb520b556af46550c27cddf0f6cd5eed138c1b7d225278d1d5f115848a02482587e925dc625a5cbe223b126d82f6682aeb833a5cc73a59f92dc369c4e4bc8272e1b08c34b243fbcd4d3526997b775c76013da42c6e3292a31ebcd87adbfb6543017f3ca4470a837ca0b9d50d3ce462284117271d42bb1b9284fcfba8573a60dce50d36d49a211175735ad505980b65ad46e4e1d57ca0ee47750d7d9f9aad3a6416b68d1add811c4ece80ed94645483de1d5049aa5c3c70192d8392e117fff0dfc98f48ae0b160cef3afbb843d36fdb6184905c8e94a3ad6dafdde084a6bb880f7ca7bba1f30210f4f930479c132d9c1a8a536e31cb2f23d2082bf96cb68a76af94302f429519166a3df86190c2999d97f86430c091b49dc82e1af44abd1d6d9e90df8ccb5e055dfa555f03ad955e0f688c812447b5e7d13ed6ac6ba90c1733dc264c6bec802d95168c17168d4d657914553ac8c6d6d44dd63f09a40466ce9cfe1a49d889de83a53cf42d118822ee27965754943db08584331ca9b03cc99da43b87f1c6991e395a157d5233a8003dadee4b675b1b3aaf0284f0534791af3c554a58aaf490ef8065b47af2a12c374a06a9a17354ce4d3ed2bc658ec99f222add692cf96cd72f23724a96314faed378fafde762c04931a3c61979663e69a606ffc5223d00f067463c560587afb4c1029831e43082caa6075a1a42d9f98dd59c0b1b25f5ec51b3badf3dc2066139cee7458534ee04f2605e740c54f66385e4a2d30fc4c5a7e8784e7c4862e362850354129632cd37477e5bae6f8e6d498a5b1bc22e12639d1fed3115b250e671f079b73d47117aaca902f8a05bc22bbc903565fa83944b3b21d3418b01f86ac3b4e63618c638f42959969d101df9c46b04e92de8c69a7a0a9c285c57b3c0061182d9dd9b0052615416f7a717f509460c78d8715d65328c400bd5636af419a8f7bfa426e30ffddc3a343ac5db3e7cea6da8af23c2e298597e8f159004e8ebad4858a78454147b69afb5f6bce691e20f89ef3c4ede28b3088534ddde06fbceacd0985a3bdace3d5ed3e94a809f047f54644e8e7d0f446a5c55bfac074280c6f9dd4323435f07b8d1a2af1f5391647fdd27b1360acd2d1f25b27f938470b770016f512fbd6d65bd706a3735140af428b9b58f877315fdb279380df9da8b430a1b4db2650d4612d026820dbbe809dc65ea82909c071ee87061a8ff9ae1e10fee856211552b3ca06a87422f173bc209d816ab8b9fdb60a875cf74de38adddb7ab38c75731388e2636a67ead29d3f8777f7e75daa2dadf65c1f93ddbb5351775e8eedf95b0ec8a908ef6b2c34d28df86e0ab1f83e9f3703bb3ecd6bd0b1f0610783aff82d0f78087278e8faa73122e08c51d90a06c15099176778ac162d7105216b5a6d700694a91c452e83ecddf2cb39c95e0a975cefa131c2ab9ec90d9a486c970d4a4c0bb80cd6b729956a62d893e8670cc7aa61c7ecc306f727e08abc50f188ec64d5d51ee2d33ec70d6e8c98a1f0d7419acc6fd9b9eae337dc0466305b34866d58055f95294780474d93b71d18c824dd7918803370791d694c54d041c7fb2ee2fa42bb586b8c1712bbbbe0e08f5e095e1a6fc61eff7b34230b9292937ba4556c9b8b7f0858d9dd7d0200e246ebfc46a33b3ded8474f9824607e2c17580c429b8f9e077ceea392902c0180fbbe9727ff7aba696b5db2f2b9504a232df3846cdbe4accd81fabd22d60bff6a7e3b8397d37735124b9c7f764e88f51f680b24b4d34cd615a9ebfaf176c785012d0b5dc3b7bc95295be4ec7c539511ed0327db998f41ad59c3687310d8739909977b25588330622e53e03cba7679f3b4ec73f5f0e8dfa8485640e9a03970f5dfc23f914b9a1099973ab2b2e8b5680f1d03f395dd26f38a06f3d9458de8d1c517e598d81eef5ea6640e97eec3b5c826480d93d05484038768349ca5d18ccdc8be246e648ee677f18dff05dc3890cc3e95120e60766edeab079bb786b28a5040cffe770521e19a19b27caa41953607819be6324838328afe7ffd91a7968ed63bb0c5c85f698c31833c5a234dc9d42dd49c5b4045af807c378b8d49656ee336ce7fb445b320d1038a9c0fc94be09b6566fd9c59849cb468895e9d0a5e5906be6b1f02b63b762c98c6e878b4458d9f64d68b530805ca20074ba34e8603346ae6c92a1212e4b10d1e977c962aa65b13b277d63e74f5b858e49ca1bf093b48b43933e9daf68e0878fedccc6bd928345e27393e6aa3b92d09b1a0926dcd61ea930200a4dcc55bce3aae63aa1096911663283d3d0f57287099a43f7213246640b08e821f63224b6311ecb58929dcb578ebb2499b2d6840253e1bf26bb075020418afb0897f19e3b61c6235784c2d90e0f345c1aa493e5ef7de00ada084cdbd3c411ef75a3caff105dc291e00eecb8c0c6416ab3bdf792467e5a92d7a609d50e5ec6655195b6ababa7bb192db743ae3178110edf076de0877180ba92c5fc78a3e97a914030d1d20080413738e9e30f4edc84b8b982cacc0108e2a983db7f23619b16252003ac480dfc201309d3d93e6771ee340de11859b988e19071676a7d733aa402772f5a3d5f2699f5f22e537d366354a46a37da4e6a33b077294ffaf3746dcbb8849dcd0f80f7a08370b1ace7c3079b6c83a1913729f68db5a4d2f7867f17b233c9e4ff6ed7fbc8cf0e9d4fa845a03a787fa08adab812c932ec6c359187bdf1d16c6619da3221eac0da810284352362a47ccdbccbcb2ff755361531d888091ef4ada0b696e1a69b96d87f53a51cd9631d172176eb0ff8bcce6982e0c834bec297a4ddc2b6e09e9657265000000300300000000000000000000000000000000000000000000000000000000000a8faad192f82ac636cd9497c9e458cd5b28cd923a722dbe97ecf98ab83c7b7466bf03eb0d089b1644a3b88838a627bce3754893c8cb44882a578470c0e07f4af0e9d4fa845a03a787fa08adab812c932ec6c359187bdf1d16c6619da3221eac0da810284352362a47ccdbccbcb2ff755361531d888091ef4ada0b696e1a69b96d87f53a51cd9631d172176eb0ff8bcce6982e0c834bec297a4ddc2b6e09e965ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84add3c4fdea0b4443027a17ca585b8ce2f89dc69d42a0611c556c62b15187aea0c5b586c2b892d872fa5a038fe6171b0a433e5c524d5ae9d54994332c7b555eefe467af065208b25236cab7a59777534c1643247c0a4b3d7f42d8309f093b7843006600000000004200660000000000ff81040000000000a07bb4f7ebe54c991b8f8ac6f3570370f2f88525581c785a5d35f4195ee689b11415c3651a3247dbc5fb0b39a549f5656292f70bdf69be142c6d047e6aa0ab2400b13d98a9ca474bac23732f9e7489760d2e216ba5162ab01951309938634ebcf40000002656f143437cb74ea68865dd296c08ff122ab1f4de8417ef299950428af70b68336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71384236da69d4956e929c3083769e658b44b41d4ed3005816d5fa327352a595dce679a48605be2310d874174b9d3cd298e529c3e0a73e407347b1ffecd30336885124fcc2b3f99f571ad67d075643c743f38f1c346e4430d2cab564dcc766fd25007fd563b2dc452a28b0467bd422c6aba71fa8feeadf933b4867ffd7e972b7d5411d1ab0f5179b2b1c9097a02bf8a1f1a8b65c8641210023ce64360230218020810d62a4106356085c1601a206a9010c22a00a00680423c902444818f851120c408019048a04000898103d2407601f123835a4e508884028040c1a4dc807c74e36188430611301400154384082d93444e9f61302e3420041533304270564110408021a2330581e1208f2140400010a5141182ad641312258a0c4089204e2409801064144000c0403e90020086026184fd03900a08aa4856008827400aa0229e01a3044028d400323442202239484224901c20ad14108109e112000008490000804ece28080804c05022821520b15000e0822e0002031a00801a0028000dc2688a00900010c101080d13800d052019a052301f14457c2dc79a839c731c04641317f30bac151a3bd6386297d05508f58527ba7adb529110b010000000080c3c90100000000a442a700000000006f338e6400000000380200001396143703000000000000000000000000000000000000000000000000000000a988adbd0bc071dffebc194167110290964aee087071da64118e555313c02f7c292edb3981f87eeb03704a232b476ce8fb3e73ff03a16264a45bd907485e59799218cb0b065205024eae84c79ede8f93127144c141a42840b1b77521b48d62906631622e696f000066000000000035620500000000003fd4154ebad20e5e48f5283a94444199024d004a04f2d021b8f1d34cd758fb4463c30e7f8ea4d29a514e6887a0ba301e0458835e7c5cee9d6f74a0a98fd3063fb3c289ec2781c918aa8aec0d30d49cca0bc5fe9cdb7b72775ec3aa6035778bc7f4000000f1f29da89ea6dd9d217034d581624e5863f183caad5227e7da582467b5e9c97a336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d710e549c6ccdaa45b7f4fbca7a4985682624416067bf12fb23197cf7ec6101a9aca20693c2c4c5333bffdcd97bb30df3e883af6905b042497d5a599e76afd00b7c690b9a9e9aa1c9db991c7721a92d351db4fac990ab24b482f3f90e6bf470b09129f26d0a48d16f4403c395a295a86d2bad594bf2b3df91768e08d546dd0a644b72dd50e508ef836c67e3a7f209f2c43a8cc8c40d3a71826eeb4993b41d0e1ab4a22562355028e03806007b51028124e0fea915095341214141081b4910521464a0b325761babb69888c4ee1003461916c16d17f0159c2018e6049a2c1bab66edca0ce4a404a751e0e1449b5b26315c149a20e29152ea44009702c3050e5038a0d4be2851c8d84641414c8503bf50afd2884dca156a424c500a204f73d7dca00d13031054c2bab5838b00db88fc35014c80b68c368e930365ec0a2b302a83d5ef9614ef563c604e10e48ba05643309e6356dc1a71009b18a3b116c4e20a01d8980cd21409810ec2ddc9da321614858862334c789a0dd3fc595884c09878d5ea83f56fefcecef39651bf6dd04c4cd81f1372202d178f5364b0cc2ca6012b6a890c45f9c558802429383be8ba0a1884064187848c32e7100b010000000080c3c90100000000c59fc9010000000057308e640000000038020000e3ca3af0020000000000000000000000000000000000000000000000000000007165cf8303190aa4432936e9fa946b2bb699f10b3dffc356abb1e772fe12ca3baec0190a3997996316d017a2496e5bb4ac498cb65ec8ce2e85d793c32fefcc6bb24fa895333d0b64158d1a3440297ae299b35164dee07917b12f9213b43de377627920406275696c64657230783639bba4da9640620000aaa0f5fb99365a057f50846de29bf97a6ea076bcae163e932a3883b1fa474d2532766dea028966fd22a6892ffeaeb95bb9a7194ad53d2ab8aadde71a7052c0906ea23e9d63eca689de525e8aeb8076abac3b5a59a7067652bab32d763b7e1be989ad3b2e3b028a6fe43997374c09c3ebda8dcfc45c7c06f0502fac1c87f7d42748736069c57e122ecb5aca6c39f2947e8258cab2a8b8d055b0df23e6a3005c0f8ee504e20d4d3318153ed63a850fe91bec02b554a4efec6733d2fcabbb9e097cae551030a2305655ff44b7c48b3b0dd56858471ef79a17c06bbd39b7e2519b884c8ab9304d53beb61956a1a547d1ae4d98c5c592201111444cf483460dd0f9ba620aa487f048f161c184e2c049eadce8dcbee40e6f9bd6dfab44a234576e4416a11cc55c4ebbc66a0894127a89ac466e72642df99fa4f1916e0504ccb269b9ef126f0499e5c1a2000dede666ff98643d810f7afe3f4d3ca05c794d1730dc386928008a67e52146c0a72b5b762cdf84d7f4771bcf00c250bde526c7408a892b7d86be5b7ccf9927d0a3871c51f5ab5811bcda4ebcfb4f0c3f2e0e75e2643f2645092bd07f3ddbaa9511dd4005d96da4638d0145d562a01f74a94a8ca1f75e828dbcec7c80339019435731c83c5d666543e4138c09e51cc13a17d11b7db6e979d78c2c46c7ea1c22a8cac34b060be8364b463a1c6dc213eacce183b76496cb9d8812f55c60f48e32ad3d087ad0965e53948a094a10bb067925adc6e43833db3fef88f4a9920eeec5b44e410fbc54faa295d50dbb68c395b7102a5779179f2960efa99601f186965e8744601d1b61b62e4d892261bef2a561aa8e6a130a7fe81a9f3a645c66ebb20ab2de1eae983a2a4a71b5046fd389ce659ee908ade8efb7d4936679eca753d3eaf407b261897504e16b030406435cee67eb5370ca4ccc8cd9229195a195d1ad572b5f5de24c0fe11709911a372a2fa5ef4f3e6d41d4a019af83dd0735e6e48d37581179f96b6d9a965cb06be41a8156ef52f04ec815904a34398b01db54952cf3cfe12548364381bfca52fa76197d31cf4229a6653a92bd6fe3b22b9aee26e65bcb7ac594aa90a735776be5bebe334cf5389176cb362482ddb88b88b77bf76f922b8b1e492d45ec5ebbb6611ebf11ea610f9c61b60fba283c5dd91f8814d00c790de042651eef58a2ba1931745a640ff3e59b95de9b7516b250809acc725ff646c78f254506c5f30c42309edf6daf638caa69ade09247ca3632abd89736f4b196fd34cd5f148c23ed66b0ca5f7bce314bdcf10a394261640c2382c242b9b00533b2a4b48a72a0c816f3c9afae20231b5f14482928736afb8adfb29afc6347e788b41bbe2d78cd6a7d66695adc227bdc4221e242fb764f4ff58dbcd0dc758cd7b4503edf6ed1a863f80e882ef26d04ee67ad86f789c220c76f4448cf717dbe694aba2d19dec909ce9988c2663b27d28c1f0f59fb6dfca1d5407fad309f546dda06d0c1eb1dfa6f626a5a6dc808679fa60e6316b41fa9f5a883dbe84588b67a46d7530533101e8985f732b790fbd72c18ba86d6b89cbb86c900ba8c94bcee20f8dc2fb8278541cf3374f8ab51eec725a6b4df5bafa86de784464ba32cf776f2a1d847f3e5683a940c710975a955328f3bcd69e2ef5d4f816e96d7912bae20dc038425d9c99158212768afab4da0c4a0a3a4ffd3dbd25bde327a51df8dd21df0e156f99d2b9826328461b5f07403d291274d5230bdf88872ade7a7a2fb61acb8ed39ab669a3f14e132ff06a22f2fc3cf37bf3b2df42f87c9d7fe79c75578ed9b900b4a7c006cde0aae2036967bc5342cb9eb29dfb282c13cf5fccb3288f29ae624d68a2824448278557e68d319d105314db58317b36c01b0f29c1aa789d485cb562923db763e1eb0b33d7f623e71c1a87bc364a61623cd2402cb87ec0f8132e0baabbdd5bf27ef1a726d6ea3d4e2353175bf9786ba894cbed149d79f2ebf9f3fe7198075b9ea1572cf830f3a73eb7197cc3b6b61f7e458b65128b588216292637b0a96e109da1daf030b79487d969240fdf15fac2152fbfd5583a78295920d0e8a39dadc5b43e3fc2c543395a4d578eb514ef104d5398a78b13b5ef398629d341735103079ccb10f871bf1a809961b3b4f8168226366596cea0249b174f1a5fd72ae57c9a3a01fc15790eb226d5422550ec9742049dd4ed2435253fc5d10253ade053962cb0621ad244ffb94bc96da87302b1c9234e62ecb03fe98ec4fd45234d942842cb3f1f0ff665fb13277dee1008ac9033d1e9064175dbc66a25f61de2ad170414c9ade0535524730ec110b9ea3762bd2d9db5a6bb607dcf100f2391cfa0a927319c2e6d3e849b1acb3fb6cf506e64e1d7f96f3b2d1fea33077dac16910b9653edc8a3ec054bc9371eb06935f640e781f95aa90e992dd43f4a9e4bcce8d71244878671de5be75761ad7b884a2be0de1aee687da9a56fc415f6dc1e2b32a1f0f950c6c5fd6f96236708e3f1ea8ea01ddfde6e1a8eaf9763a09cb080821ee61192ba4b63e2e714ad8d084faeeb5fa93f9fa39182536fe4b34ee800bafbd08e7226a90aaf653d17245f9abab98de658ed068e20e7c01ce584b01ea5770c3b1563f1fecce4e6dffe784109681cf4fe87c98fc7cd40a020c162db3b77ce18a68e612a4869be9dc06d75995384cdad04aaa26f83c75d2e303b481b0a12e2c00a54d1b613dbab7a3f6c71cc486446e2d2109f1ad2007c6bfbea3c01ed032200cd6b16959964325b75b814c76b4d5decc8be343ecac33e982191a8ce698ef5f71c81b8cf678bcaf1fec5087df17925ea71e8316bcc4a75cf6c33469a89193e80bc1a72abfff39f1ccab59b340134ac9e137efc8689dcd6c9682579731fbb0d403dfa4e3335199da90e044924ca073ac838a444da285421f690fc42dcbbc0f5b8d0c52c68a774bb94dcfb1ca293c8b4cf5f035fd4c7446b5c2957a7fdda7b5dceb387169b3924b8bcd07a1860b4ca5f3f1204fe7cd39d0babc579386cfa4283d6d40263c67c70b9b2d9e8facd18334b7ae33d9bbf5430cea1761000b7d52afa8ba0b46852f4a1fcb1bd65b16113e99ae752bb24b33770ac4a7dd4db6ae95c9823ccd3e287ec8e03ad032f6e1734b2cfeaaa61714b709985f4d24dce8d5d9b06cebc86483d3e05f07a0490ac3329610b882b2083008076ff386797985a2e16d4e58ace01743b8ff0920391a082c27c75c36d492ed88a198b8a8f5747f4a8903c0e04efb25844215c1db3fd148b43d1ad26c7ad2260ea20206e9038faa9091ee1f93acc26613bb87648d4e1f1dd08b09d5cf686dfe57e74ec517eac2621a77564ae86279709ce54bd55d7f7474b7098abe8d177012ea78ddfe5ef6f9fda0add9f35a921ca64ef8763533029bc79d02de21bdb47fdbc7ddef1058bfeddcd01f2ef2aac4b915eaea57070e7ca31b398213ee3365dcee6da2a1e200fa0f32e788b11137d34ce482a57ba71707e96d5a84b79891c57094db2984ce135f0d1fbcb41c427d65eda85aadc63e7e3cf285c809c16dbbbc1840ddfa7bb4aaf245daf99de4d885a1a42a0b42a3622bf03226d089e67c3f9d179651dd4cf39b1830a2ee274de603274dbf37adebd22257d2715e17b39b1989eec1ad159d86d5a8e87497a3d10f4b41e4684f42c69fed29cf3b08920afac98148e329fb9415baae8f94af8d738cbd8b79bb110c91c8ed90a803f8af7294cb1d4c00be9b81db44cb1e0a820b823ca686fd90341532e9eec3744d7d90d0eb8be411fc3b57b0c5d116a89204b36c28262000071d263897ce802a070829ced96c676ca49d671f4d2206df76f864a903960c6698c203990792dfdd34ff821b5b1f454fdac6f099e6804cbaaa552fcd5364f7f05c7fb0812b7f86b7ae2386b2edc446c6770cd4f329475bcf3c2795867f9525b0deefd82e6cd5e8dece7035f04be0df84507f2fc202c29b55e8d7cf3c5634678fdf6a8a8ae9e6ef8fc3aeb18fe852304cea4b38f7b8b98272a10a44e1baf4d9e3e684b48f4d5b8746ddcf7d1801b3a3e31a5909b4d610f88f8c5fb51cfb5593f05eaef9cbeb3c0e0c17e4b3da289e1c2e11754e1d414f9d81950e1553f06e689ca280e86f3606c35ca0e191adcc8c83ca51350a99188195ae0639e6419c1c08446a6755ed52a6e023d6d576e5afc5fc5e09233c9dbc975a4ba829a390deaf6d2258797ee68abea993a5f02e9c23ebdba5f9f2ae02b0aa8b23b3892ba39cbe354223f18952e4592d0958eeaaa3d4902511d0b22c9e43086e7761f73c9e9a9cd3d012e0f15c22d35d0ce082f36357e9cca8c34666421b0183613da7ac8cc6a4d5030a9916d34aae4b9034dc1fa13aae186c6790119b42c6df44afb87be3f98f5a5b721221dea0a0a78b8949ac77834ab615c4ea4796e6f63480e0882732c3f32eb71d2f2ced170a72a2b52458156f25050e5e4482bfef15680e802fa9e0079504a7068f176c6c30483095adc6da3b58c65a220393e596897561290ba7f3d44215b03fd3fcd2632f251b363292520674b07a4d7e589430bfbc38448e2e0b92a0d09c87ee111312175977ff0538805495ea4b1460474e676edfbd6ebdb2502df59b0cb3e39d5b569d833bbd61de57173963a18930d6b642beb0941e685a5007e923c249caf74260ea81f35b6f957b1307c4e7112c621eb0b16b94fffa9fb0d112118729225644bfc0f88f0a8769f84b3b327a84bf6b998472ac60cd898faa76887c10688a55eb733178f9202af568e272c4edce1601957b47e9340e38bb6debd5a7b772badbd37e0477131809994405f42590126ad3620b214e93309f4aab6830ac1ec5f2d6cf1185321696a7e92a3bc90c1ad27cbcd7ea86d08ed94280770569546ebfef0fc613990d25e450ccc729ab5bfb91a3a157379142b9627221c6b82e3c847dabe626289fceee6016b03fed83c9555c06ecc5229d3f0ae2fd62517b3549b0418810792ad512e1087586db6a421d2c272fc43c43311141f8ab912d6cc84e922a07f299f53c4b42e984418685db734df4dcdb01a074920615f2d975f10b39e6aec1ae70ee722ba3c90e86cfcd66c30be4b49a63e6469acf7a436093d48b9f580728ebb99e4a28d4255dd9b66e4c44bfc7aecbb88631ccb5f03caaef63f80c90a790c6b9c38c85ddfe673212e0191b9e1d237096203650bc69c38150ef976eca186f5904fde13ce4eed195023a59f1bb6c0401152db0503b72058db372a3fecc5e50d1e4c36b4cddfbd4af5925374a5bff6bb885591f34b5a23fa9be0bf847050a5b2c6d59f9293c03e8cd53e021fd8f945e2b4bd9f733976222803eace8895c1380152e13f3db2b3a9596e377999e1197ca914297bd4e1b66686bd320ea6c57d2ed6c861315cb84a34fc415a6065e49039039396ab585317ecea8afe2307bf55bc035d04a1c67da5f3e6deab4e9ffca6581706be3c6cb163faba8db5d82ccce796eadc94968c967377eb6f6c02a3043809ec87f62b35cae8c345898155be7356837ad62ef91198c81c47f04133828d26a562c1432dda68e95cc80952663ec0a8f07495cb9151044f0e19808e44572cd29bf07cdc21163cab418b4b11783d298b8694055b17e6693b59aac340faff24de8e3c8553466dbd4fb77ee3d82ebcc33c4e673480f590bd869c7537798cc069ee837fed07404fb83cbcd87c30246256a0220831a65aaf4f551e8612a16e54fe976012595cc28cd2a95587e97e6f2f1b11bd3f48d7b10d526ba55b63f11458af1ea18ec8a089e7515c0ab3f0b8c8be64aff577e3eb263b623b55067f8830f67f14b497a356ee162d2d1b2a6f686f8eed4de58b67e335a3c9ff6dd16de5679052515d51a75e4497a886757345809d74f53d875b498367abef74c80910a381b08a1a5737b31f605d42b90384e401a8711033e0a9336710e9ae8332df29ff06217e8ddae210649876fc1a2a980a0ce662a44c312c4ba974b3f69bca03f95d93fce42937adc2a59255ddfec6fc1633bccdac4dc4b9eb5c9802e84eb9186cdc9ccd16b108ec192a5334836f782c02f58459cb00b8bd29578f37bf1c4f68b1088c951485008c1213c581ec250598a25d435440c20d9327229d776e27b3bdd9f74a23d67c5641800a91cdc1209c55d14c73ebda4982e099d033df09a9bb5a5baf5761aa857ea25cc7d45a253ce8ca24ece40edac5cccd6d66f7e1f9f207aaf77f816db6094f49f5b279a06f06a4a917fb18793a4887b29ca771552dbaa157397d283bbafdaa21f49c77d5123568640cb3fb93676c4d1a351613937656802b905e1f8a945dc8879d66dda54a643985853709f266b03756d0d19c2c7b6c402835f0b980e7fa1b7ebf134011a9b6c52ae80e3243c16f91f03feb1bcde34abf929304d2a29a209e8ffa81e2ec13fa716fd7fc38d7e07193513a4607e0766eb9ca3c6df67179e92bf29a7031ca6ffa4955b304d7a081633eeff279e981d20f4b7b76c66370bb5c927ebc0ee9afba49e7a80585858cb2212e279d15506fe837c1dc9947b4adbe43f5c8cfe8589c646c27dc6d8bff614c3a22477b1ca41e6887c48a7ac3307165b725d963f556abe4b40556b7c1da0e88639e9515d75630053317cffa7f0f315ae4aa9f0bd5a247b4c972b8e3f89901da8ad18665e91f61f1b4b79559be7597fe905651da59fb903172ea9ecfca78b96637f80334fdd83f9bc90078aa88ea6c503c53d2842fdcce8626eccd5427c30f2fae2a606229503aba5f9b4191c79c60d17068d04c0693a4e5b397daf22977c8b5388473301e40b5ff0ff6b556c30403ef9b061c5de90f9e46e9ab7e960ba0499727153ed9581144bf78c66af201ae8a04a283dd877fb47909d899b5552f22d713ed938a0961e0be4667c840b1609cd65f1f00e0a3de9231910b103b79206234a96e5d2dfe2771330a387bb9ded5cb26897f02beee3a1c299a253daffff5f4b9b0bcc000e82f62192514c268e048805b5380594bb71fb4ec5a050b3c1d16c2734b27e946ca68a2d24bc83bce8e153a8c2b63e828c93c42015903af593a42bc524264f0402367b45cc95596109793d4c53f8c6b3f877aa8a04e1236187b0b7657b7aa43c702b4d82384afe3ab390ecadf144ed6ad906f320003074554e0473f805b1e6a3a0b6790525aca22021ab0af429ff74f7beabd138f00ae8728adf4a447f4ee304bb74f51bca38e64e0c0da93c473349ee4d95fc2003d4af9cc39a76e8ea9fea783aa8a37c12426319a86a1e0c6d5645ea81ad5d11f5f25954cff535da64ae898a7ea9c12e587d88f0af5ed5f23fe89f4f03c517bc71d1eb02b228038aef227dc70485941ec941d31a1a2e260ea8f2b5d18ed371085e44605a4dcffce43b9f17ef0c251177e2be9bfba01b3141638db6bcaf472130c870c794e8f7a5b614c885f5d0fba6a8bd56e61d6e67439ec1e965cc354c3644b231cd41a0f30ce298181d29da47c73ee163af3ed09766dca91944ac631756da05905db0ed18a1d9ad6cbc500385f12738216089b1126e1abbd28b3a111cedec1f850f51c573dbf56b8193fb78fd6ac724cd4d0d274d6c047e7e86622acda42873d0b2f1af09ee51e53c84bde61de255340ef23cd582f988398db2b8205df1f2056dcfcc3faa4b2b3351cbe6a2379f7ced624ccdb0aba2c3dc17d4ac1e81abec8965939801a15ebec68b4a62dcb0b9e3d7ef046dba8ef951db39a2282bbc2ebc93a8c7ca823bfe0182246b48b31a7b10bac08a2440d6fe47cbf3a4d82e28fd055ddb6f9f1fef4b71747725d955b05ddcd200edbdacd7727501cc66d5f4ce08f3cb2503aa77d92e61982ea037877f19fbab382489aad066e578c2ee754884deb92a141a01a20aa369a5b70f1880704fcbbae7191887b76e4a32d13529b8401244e504f713d99768b010cf9dd18a125e75c8743bbdb1b4e6d5726b8c9b0997b8c26897a23d0a37888ead66da68c2802652c96b74719c42af66e81b1f38436041358a9fe15e825841da1d81714240a61813d7db6bdd46c911f72885afd135d62bfaa2b4c7f8d5fbeee79928019ab8ede2aa454b73a5a28e6c0e9eccc62e47cdeba9468dce99140bbbad810d34957e1f16943d4bdbd00fe7ec9af78b236300e05b948c38c198b8aa396593f656d05a177eb9d87960c03242e9e7fac2f216e91b9b081aee9789137ebb611ec669f47ff8d6c5639ffb1db9f9dd0dbcd33df792164402cc111eef90b37c45584c674cf7998d537f83888156ee6f04cdc64ddefed76b2c337da6f2a4bd3faad92ad9cbc359efa71e88d5bcf1fda2a72189da796ec2868fa4a9b75e6ffbd7e9c37cf5e3f9e9d608f7abf82f879463c330e9ee63865694e7e9558985ffc16679f85be3a6d5a23036fb59b732939d9f4b73130f0e25c9e1d3bd0ca0d3a8268e52eaaa7ddcf122354ae2e9b72c2e3a49e9fba365c1c19f47f01c1e1406b5190ae357157750776331b6da2539ecaf5d6993ae63b35b7b4ca3685d300054ee18dbca259f0e9240522b074fa179c1b7ebe0c016046fc51822582d3043bc23818457864775b744274a88d457ec67dea375738aef40b00af9314684a014b6a37ee81ae41e120c7a6be98d5367c3d9c6978964580783908f8589b09ce1cf8113abe48f1565bf7a1a58f29b5ee117507ce1b43ec0361151cce1e9cc17ade7ebc3951bdfe6c7181c9d503265997d12dd74574e91e9f885a7d98119e90ee39e3ab0de787ee786337db447cac91ce86edae499fe9abb49c13ae9bf6060b5099c2a591ddb1180860cd5219f18605fa9ed2680748006aabe863ec2a9b3c47a4edec49498e5bdcf9db0c9d32b9ca1ea9a9efb10685056d2a8966903723e003c2f410a8680f832047882977d93e5b0159b6057628c50cf2fed2cf115290cfacf640602aa87f78d58151022dc4317a3dcb9213ee98ef3db0c011f14f703d368724999ca859075f469631dcea186e1ebb3ab77b38850bdf8e154ffa55be8ccc6de71a46810c4ab70e302cf03aed66350d85eb781f5a338e5f072ff41877ccbdc7602b6b2851b16eee9abfd8a41a452ce3db99b90f28e6f04a928bb3c454bc49476fdf5916286639e55a9eba7d7d24da7b4e42d59d422f11ee98bbed3bb7c5f61939452068cf292d70ac5e84ade7ddebd540153a45fa1f1fb45da59f351a36764bae46ea07b0bd646a1d163a05088a30fecff44a769ff62ce740cb6674d8ca4f7d94d133511a8dbb3cfcd146c0435a342e112c294b88d4dfda5dd6ee042840b7f7dd7571d29456feb549a86d8ec35b74c0047f0a80f93e0a94600eba8986cc8302b2dde6b37264b0725d5fd4ed9bd9688a84b0737d340a0126c9840bacea89d000d5e808152865a7eb967736c2bd2d9abd64b9f67c496f4a58d1c7c503d77b4cc8866741ea4436f71c26d0acc9d6d312165cd17405da969e573a2a9bc35b6f1173b713273ed739cd39a9d64f598a6227fb0cdfcde119efc101097ef92af4ddc9593599d382695205b1cf526409b38cda8da36fd1f7d1ef5f328523b47ee15e7a792cefa7b8cbc59e8e349725b219805af2971d247f8b3a90b03a1c5385b1a5f4195ea28a4efedf6f376cf2a00ef34badda545bba7fa665c92374f67c1f486c3e7551ed0c06c84dccde52abb4919ef9561e1174fe44ed3707b35f76e3eb1d5a2b9d73b499bcd9a5712117c90882329d5b39d23e06b46a1d82c66d5d807d2901eb09d91ea1f4e065f671757d458bed399ab3267abfe9d3426967530646ffe857a55b689b0f967875ba99f265176867036fdca486073d819e5594450b1adcbc300056e9a48d74a9c8cdd927a40c463797f47c3f431c0d98a2275ce7013991bb3c94d6e66dbf2fbf56e81b5623e4c092ae87a9948455423189b7bc946412e983e3d1cd6c6caa951b0ec683437db926d3f1c6aeebc79552ab387ffe7b6427f4b9277727e5ad5ba344f3e2d3dc2c9e955b3632fb51102eb95a140a0b1dd40457122871fe4aa14cbb905a2eba98a1a4ebecd8affdaa193c1ce5197d9d70111f4180be5fe8b8fde0d2da491c7e343ca60559d1632e5a3de5ef329c9084b2c67f5b8db1aa18a5573df567669e9741c8ca4257abc31e8cd6a283790be5a75ad5af857a61fd78f71b61e7816d8c2727b7fad5c4a1fac1549e20a698978c4db9374778354881a25b70cc06fab02fa74ff4c4cb454e0ac0643d2608bc126226bfcc32c1fcbf9608f7ccd1885f416c720985b89961f470a4e2576bb6ba486ac6f702a73c5fd7e0752d6e6962b5918962ff906ca64b450f658c95fbc48d59e727044e9405c9881b8a32ba1a93c8e9fa3ffa17cd80b5b2a064cfb049d121b6da4f3cc3c00b830273c7fbd549bacbfc078a6562fd3625f47474748e6146ea40a7a1f8a90d9172c698862848bb3f5e3dac5772cd1a2ca5e69ec59b711cd25529c36867c03446eadc5e824c1b1ede28268384c934cd5443af7ce3f80034e3eb6da4dc8ee47fed39acc613e2bf1eeb58a17e72a48aa65530f3ce3720bbab44299684727663c2349476299162c280e5cb6309be43e4dc697331c95b6c110da24dd6c283868a748f14f09e8b39afbd103893e41924d54b9b8f242c207de1598587ebfeb4dfebac33eb1c31ff8d98fbb0ba86de9b6f5ac41e0ef8b3959a703a1da856fd7e940692dd4c28363a83347d6e62fba77bfe8dd89ca2b61978301a70b9ad61789ca63f0160936a49f4de1991756b4e7876091788fc655d53dfb384dcf646257ede2773c27977112b4056675eec9d2cfab5476ec660fb850637343602cb88bf4ae2866ab572ac65532bd79f23c161a3b7b07492e3d011d0ed85df6808e1725e1e618fdaabd22981c743fbcdb523b9067222ebf0a3fa7ef004edcc4f72d2dd3a87cca93047b9eb99321b24d0bfe9e1eec4257dd9ad84a6c9de4706a0b3641876b8e4c3e682cf9b48da7f45efdfbdbed1286ab8bf42af5776e86e18f8a8fe8475eb70b1fd4269671adcc20b7e3558fb9544b9f6d2275a52849ca207d0d70ae31920ff3564e4a703747574c8a9d5df2bc4a79fc2025d6293877fe18a209db4d8adfa1a022ac7fe590d2fc5e6486de677deebc6417bdad839e5706ce33909d2620feef208de375d3df5cafc0da62b909b5c0778fece89e748d5b2edb67c2d1cad7463f2b15998f936d0a8145a04ea7f2b48ec77b37508acef0a6af854bc305118a170c3e53cecd028aa350697bb6ec2ea4b996148dcbb20b15d9d017629396c234348a9908eca19cc1ca5ee55401875b8f9e4f2114ba19b686623f9140c89184fd67ce51b6afbda94d0c0cfddc6918154cff5d34b5c24174d1fa6d93cee7a3bf957464fc3f4a884189848bd4946350321c3eb973d92914567aecfca75ca46be7c9341f15e4e22740e0275155eb124061a649faffd200701ab396f6213c2523bbca40cdef1b0ab992fd42c51fa3dd305e8fa72c67f1be3c629a0ec5c113f188afa109ca926628b149e35e6fc3d6e7755e4ad50e5f50b5c188819205ecd068d5601f5f34ecdcdb7bca88f2db0825039db7a30b6dcffdda7ca60db34f3d1db40248a984494f224f8dc3e87583a5db404b5fbb19877588af10f0f06a2303b38cbaff9793cd73b7db1173782d9e0fb74e34346730a1f086178fe5052241e836fa9c984f3bd2030bef96b605d79483d4834a7e836dea430de7bfe82205e220234262562fe7540c5928d078fcdf4a55949f36fd67752187b87742af7d9258f74879961a9316cb988be7b494e9af4a4961bb344719f710d06bd4d92852856009508937a69d4b48031097605fee5ab9a5580b81f49331eb24c7e6aa0366d8bb618dc4643b42c9a0d241a556ae609d85bcf5b71891e4f31ef6aef7ba5421c119ce210a8085916813948421818eaca37367b747d52813ce5cc079da881e540de4a4532809ec3d7cbea233eb65143676597836441cdf967fd8e168df406ae154225c6568d070815662d35f08db831016c10e483350325c7ff87a6391e95b221fb8a6a12200f1888903990e8d708921e594a1805ef2dca377e50462fb30e900add87830807559dcf807c35f638e0be15cdd88c46a1fc0b527deee5edffdf8f3c0bf5df29f8ebc99a6d561957a612aafb01e1dda4c2fa7e1ca6d285685047ce4d7d92dfd9f8aaab06d24c91e5515e10b26319b0f4cec78f70270a91f28654c0ad3e366b986a594b21433d4e6e9e5a3e0ead7478543624c8f3f0c61c55421b6b56de787b1a579377ece2d2a675cec9c67e7ed32a5eaffeda8372aebf75633c58899ca93a1312e0db85df34bdbd4666c83f00c4c2e5be1bceaca6ff8014006dbf5254bbd27ff6b5659e8df932a04d3e663e00d96bea61235b6558b8db1a3ed3ebc17d647e2a5ab21473b583d07ebcf5e7d909d20241530452ea0b7eca4ab53e0c7a5d275fb896ad889568504bd6bac7de1d9ac2b97c69e5f5d7d76766b63a1a533646cc04c37f4963e16da0980027b35b1bf080f00cb7489b6b61ff2644e259975a14efd6654f6c0ab638b163de782a7a4c75a890102e53a3e68713ca745844835fadaf5ba12023d90653a3381b774aba6833d4fed95cddd7d67ecbeb7b77976f537917c83889f5f8024e070c61a59cf9bf1c818148754e0b9dc1d5e0a0a48fb2d7ea1ea8e11be9045549bb6a76dd0d09ed1562e4c5cd9d9ba1683e89bc9010d8e97a70f1a94d1ea8976e2b1421c7d78b85f9af990c229bbad0d57937b3f13c5c5112f052572cd898b0944451a6b3ce55f0f4703f8b95955aa1692c97bdcb8d331eaa8f035eb6afe4af2443873c17b29892c527325cded324e86f839caa4c7578b0138b8bc1b4405a53199346b5653e1cbb63a47cf7ac07fe607de68c971aca1be88405c8375082fcb14801839bf1cfb0c9c95edb30e9ae6958a081e5264ce326b9342a45a6b69baf4f600ffb618a8bf896f3359cef8d1d1a124b5f50b2f962f5fc1f98dd5fcf27f96b53ce252087be5b91c3bbf5431910ac136ce4d0e6a58a7b63140cdc35bb5edad97ec2a550d56ee58a001631fab420d864e14e7cf26ff14bd3348f2137ffeedc0d36ade07de57f6c354306e1d948b1b02ef60216d20c44ff5bcec996095d217ab3ce07eb07fd639d57f799b48c9be74d48c33747c11cc89a3eb3688dabd1351873d391ca8d50a9a8d9b1ced1fc6c06a94b8146d9b4091556e2b9c91fa3447f6bb448a2d6126d140ca86b7da5ace76b66100c8e784a212a5acaf413a16985dc98d5020cd00f854312326532ff5e9e20f0612f468150ee230e40b2199d1314b691959c6ead79fc5f9b722dbcc4641464ea651b1e268b46a0c25687dfe8837cf354fa6caab67a08a5e6409a4e61230f5ad30cd1cb578a1eb04bb862811f06ae35297e2597d7804d78763d0683374ab39611bb6360d4100761a8b1e94d4b32ab7e35bd8add8568c2f44869f34124e5e68d9985dc7598414a730537c84fb00cd39fbdf5cc50411261b09f3b589f9caf345739c4d44cac089fbd9205652c685ceca33aed34a2f3a75138b35bb7a9611c1b2356be9cbdb1c61171fd74a9f5fe1f8df3347aba2a8390d43d6f253c331339d0151b54d834cae11df355222460dfb980f5038436d8ddf9fe4ca46d458382124447e9e960c7df208876c4fc90ccc91abb04fb5d49f3ddaea34274724256309d1b141517552373fa7a5811b447a59dbff7d5ed555702cace0257ff411b61871fb7a8d88204c0bf54a362311b22201d2247f9e8d192a42ac834676af8e3c9b8f851bf90417a8e19937955a4fa44f62127747918e4e453fb3388c30c17dda64c54a22f4ab9027d2ba0e35b217693ab9a87013d60114d01fbfddd2eaac9bee7dd25f9325a37cabce47907d73348dc980e511dd22b11b68a7deee85006279828b605898f050c8a08b3ddfaec0f93cd6577e0e7abea9a538ef7e4dc0f94a66dfed272d8560966042381aabfcab792d01cfddc620d57d258aa2c08ceb1617e35fa61c61f069961f29089898b72aeafaaf296d10067a04c79b7061e6ea6e5e718894a7b50d8210c9a150af8a8ba7a85a486c26e08f969195401a2ea33f9211fb96e14e9dccd455e05dc118dad2e9ef3419b3be651ba33775b6e0995d3b2ed6a3c021f039cfe8b78622f70a84c461af99f27ce3c1bdf571ce797e92f0bda2b399323ffc88ad2803fc939e7ae48becc716239fa514a252a6344ba947b529e89aaf6aaa54f04d32c427e822a5242c7ce9c2f71fd0071f81b32c7e7bf23b6df3158a183d15cdc03899c1a232463b92e09a77a355d5ee1446cc0bcd0437efb101bebb9d79eace65ab9667ef867da30f8d18849b37f55c128db949e69a884e0c9888364b90753578aacdd65b2a8babfbce5e05be153c3637f9d5ec155b8e1302ba6d75d7412cd4650b809d6a8fadf747a450de5c15d54164d413f6790847d435fb97c075b247e7b60afe54845c2cb2170d4addb0836b915c968a48d33db21e6d1b48ce65ca306fa1c2c231e40d3fd50db111f309fc6acf5fa8a2cdd30ade081a5c59eb5fdc18cb98a08d4be047df169fd4141e2e7fe35297bef9607d629420f0c29f806267d247462cad66ba90661f27bf8a7db6bb59c0561ab28410b2b802992d038e13047289b160a49815d45491d6884134ac1fbdb0e46125f8e9d0b2dc3e9ec6bf1095a8023f3a96554df158c3857799c26500da75d6f264b3e5c1492be6b6863b68397b6fb60d9c8487fc5f1f6b5b145462f8220a45dda3bffeff5a61be301eb84d8974666e0973bb39c05b5716dfc57e67a1e00b44f774118e0bcf52e51c9801f828f39ec061b7339220723ccf146aa63302836dae5feed843b90aed1fe05c3fc2920e7586429ee60fc8f44f772385ac04df0d6de178892fe787dc33a471614dcec97bf76098eaf8741972eff7fc94abf1fc0e9125435b35e0430f0d7c82362a804aca203f6ba0fd212aec1220cbe380d6ada46868a454e9d7ca9e6229435da163ca9689432177522ff349bb8c5d3f33dfeac7e860a3ae089147d581054f53164eaa2369fb045df5fbc9c731d36baecc6286b8758bec1ae943755a9ce9499dc76a4029d482949652f903375c9a6c14eb18db319c62a01d76abf9fd6307b2f5c22a4dcb408f47032d7ad64780ec2994bcfa2e13577e95aa8fc135d110e9c5d96fa96f158ac2076c47a576f8417556ee7399c9bc4a603cd5cbf7749fca586e59a519f50122a7b898a60fc44ae48df25c915ccfb86e9d163e0cc3ca50add36d383e73596fc58b9c6f92b85cf23bf035ef2f6422ca95158193d1d85b133ccca12e6497e8eb0af2dedf9f8c28356bd3165ddd6c54ebd218701bb434f0148f5e63f561405178e40fe78bdb0fc465edb72367f42f6c4a22d864562019e35c13dc48fe8f1969d4a36e484d3dc32acfb266a2940b0c82f6e5b7f4aa9690eeb5d94f0ea15ff5c863f5fef7660296305983d05f49801ffca2c01fbf60760d46f09b09eb013032077caa6afe89e9078755375e01e94769cb020f03437e87023bc005afcc3119b140f728ee48c86e5e6bee51ee2548258752182a92f086d5fc32fdf983329f12ee6abc707d731223053ab6ac0d32bf909bae85f61f0c53f8c7f978643a7dbbb859277a4a8f168ebdf864f271b758cbb7e3ef1c123d61e2015050e1ddee7dd09c511b3138a8d9d1749652b934255df73c33f09e060029b2a2cd2c2621430a890ad72fcf9aade38735d28bc1590c86624259830a2ca13db24fa94f1a91e62b5377f35018e1366e8ddd76a3d3cab0e7036d485236ddae0436c012fa616f6de4322b85091b080ae8646b8084e35457d700c4e0397424bfb4aa7966376cf95a2031a91308283d56daf7704265292f734d570dc67e0a280fa4c60aa776227ef16b36c4a0bfcefbd133a7f4e9a15e93b8d6d0d10e5a64e96fda17c5173dd244aea836c7cdf76aed5fc97cee9bc21cbfbaacfc3bc839fe694cc3861a752952050cda100c822e4f83347eff5b654e7f29b790ec164c24c5438fadb5fab0fa2b1ed26193a929b9d4f23fdaafc71249533450da407251acc297c8c51c8f5cbaf348eada30259966ccc49d5e6e794160191701bda15f594674f760298303f28be42749be57d66b384e64f7305b45bdc895a2f59c112af8133563a8b54e96b911c2c74fc612a0856b7d657811838ecdb209c88057812db1f3cf217de546a42a04f368654c11358f022eb2e1c1a413be6535b33f508d87059e4d7071bbb430cb74957a699c667e6d321b5616fe3d47587217519e23ae09e56992eb53e390630ff716d2cf3163868f79bdd6e9eca98fda7b6048f8e6c9a5e62e1fea6ff2273c7d2f9ff2634715c373796a8a8bbd13919a84e578a58ef86befe2cfe484358c2b07b2f6a5eae726792e9f5a8ffd17a6bf981274092c70b28db3ac5877d317b532bf32348484b7287335ea9f73ac1293d5f92b1d2b48d9cef86d33e404cf0a8c94fd6c89b993d7d789dd0c8e2603f179ae3127cc887dc754652f698b417bc6b5136bf71fd2fa96d738dea6a0f0ea7f28d5f3bc9c576c6ab8d7a7117f92dd28217c30d2742e6fd30920c3c6b6305666871df23587e3c4b641089bfe53d09dfc28e35e5f8c66b0c5996b899d946d9ce85fdb2219009ab5241b0f4013fc7986ac8a6b2445033b1205f1f27c0637730c55039f54c72d2021995967fa73b889b6b73dfad60cfbcd4f224592de78cfc61616ac8aa967bd9000b2e39551b145c489acc03bb1896159e44bd59b555eaf7046091781af9aab1c6e04d77f23d6eada864293f255fd0cfe75529e780daf4c9f584982c5c00742fb0880082e36683e6467f47ce00b896f1ec0825078a1ec6e8ec737b75f438f8d74b5cb94a9f19774fdd7ac4ae2e267ea43bd286c0de6a8b2419695dd2b6ccd85aaa1d7210a77103bf8b0f9af32e25012fc078feb9e172782825e78b247d1f3d23899171252a2d6a9eb605530cff8f13a11fdc9b05e8083c6eaf0c880563ebab693ceed21336e7adb14707635b9945847061524b424d8c231f1539de00957853569d716e892d260ad2ed14e9161775e87ff0acad940648e0e2fc33a0afde245334315a15a839cf1f54788b539683952aeb85fdd7fb97a9ead1bd26fa257d6c82a659f0d46bd9f47863c3663a1f3611a6e4caf30e2ef49a8664448f9965fdc5eac60edded089d859371e66458968d98923d882243e7268b22559b6bac13bef0ff70abed24f8ff9786924e7af339a7046356d35b9165da1f82036937692dc89b87810de87f3392df4da77b4e27b429f9c32a4e7d27dca64d6ee60b7089dd688da603a5d70ca78bc95ba2c97cb874040d93f26f3fe449fa2f19ba7031691df9f40d70f3cb867b96b6d03021d75a92b7a3eb143c77e9f14bfd961893e12891a4eb83b0f42d2256a852adc4baf470b9b41d09e071c8f325087be69279fdf8840ba6e74fea280858c03b0166b03388d0d811aa9b62be03ac9633e7f20fc608dcfe5ed5a5ea389bfaff35d5b77643a5ccbfc723f39cbaeac3bb3fe48972c2388ac1dc12e022535ba7e294559e28572acee94e122b69409a8a7b2b3c53c9b674b5ec1d224c1a8c25462cb6b8a53803b8db0677cc4380bd9954ce339897f6b4ede73b8f2fb3145ab2eb17b4f88be9c545b50fab509f7b6e2409ec6c8990f56218daf6321c6d48f747ec2122c3982b24354c0d3ead4d36d642f3f06669e51e200d71f544e6df00622d6a6baaff76ea022b3b732909764b4810000c4fd919c15f4853f148b32d1e075a562a8865a26f4af3c9dce9b7f2b26eb308867ae02e49a96a605ef157f088c1f7950fe835b07277d627959932269e48bca8bc97645d192d2411f0b021d78bbcc45f8b3e89ba4bf4489b74064ee5019a651a2a0bc0a9ed0037af4c5d208e8a7a75b2da6907cbb990e4f160173042a9844f6dd90674bad0ba5914f1906bc857e6446e67f3b4225b1daf5cf7910dba3f1c3c647faafedda053239cbd2ffaf75de3cba16eb7d474ed5a8b2c821b3d3ff35bb77f19b7a0eec92367005ceadaf153afe57def407dbd4dd67cc57f6dfdbfe2509d10bd350866fed909951eb216d76de26ce7f3524a88868f3656331a5a43491a5fba971c0d6ac047032078f69099e3c1f1e6f23ca187814399712a9a5cfeebc4c2775f2f124e62660192c97f89f74b5e109baf04fd975a379940dbb8bb4f02c028d1662d7898dc317995864ac47be1ed102515c18a7defd8b91a0c76fd0adadc10a1f2afd296a80d7bf2fa4c94a5bbdcc1eeb0e6519e8b6f5ad0310b628a62f8f4fe7e78fd8827aed5e5efc0dc345d4068c04f43402ad995e69bd1a375670ad8db86c25f7d7f9a68c985af13f15078129ed6e87f4013eda07bbb5ff6ff697c2058fc7395e9fe3ce30aff6735ff2133ea2ab956c6c90882a4baa7b9cca2aa939f3500b268ea9926cde24c8db6f709ad4b85c8d5bf90d2aa5e410f35a51b40f40336624ebb4ca52aa30b1381912628ddf0f1f96cd594456e822832ee7feab17aff635d9afa4162cec3ba2e213568661067822b987e9d75f7facb4bf9f826c27a32c0f72b69259e4fbf28d90a4bb3c74f48ce619f0094a2ff8d3f633a3e98ba8c9f9444f49fe0a577bf6a9dc3f189e9c2c2f560f689e082f5f04b923aba651db52a6d2b020789984f6f74d5af26c845361b97c1af10c3fb9b388a71d86b6963092fc3bb5fbfa5953315ea677bf56071e100c0fd5e604554cd4f97bc98b9ba26b7b1e372f30a740156e23aa881453e6fbacc800c69822203e57a33a07b7dcbcae039d60f9109c738d5dd6ce301591db5d8cf434d118e72462af0a8e645a088d7e369f76996af5427d1d22f2c7354ed06752a6ce0595393d1c2889fd2c11fcc3a6d17d749acc885d1724f8aa47da9bed0a98809cf3e7a600dbf9644989c6bb06a1635f16c51b8d8e12cb0a62678fb53935784d00626c21db52b55482dddf04124e285d23349237e778a9a622bfad3decebd8138fe892149c8c1d52670a72d405a84c8323e5495534934d3cad5792f96728eeceb5ca37d7fef6d0a04b6bbfe7a425d30626b9be901da734fa5f20f1d2d94c7107c7e1c318118eebda9964251f2499d3dd2be2a23fb2a122f66d0d1bdc355a3d584df25ea4b4042b7c00ea6878664b5677582a470e5789703585dd5739609e9872b8b76865628cb6ecf26ddaaf77844c397a1094bf4c78d42eee8370522ce273a27c6634d25d1d9dba9048ac14278250b6539d9f13b03516ba9f8fcb5eda736cdabec0611a58a98f82db148a9f15558ae694e935302f0d3dd88e278d675314f06905cbf393ef42fe1782920fc09ee5853def4db39e6231f475b43173423175800a9ba22d76efd0141c8de67ac449731f8466dfa4db2fb5154e3626f2ec7ee7972c9b2ca3a904badf2866f0f498182314ea2e53fbca118390a793862053dc654473b0776254dcaa167c7c0c8796a22d4aebf924f2049ad78e3d6a6f8fec3d6fbe3ac3d409e6990f2cb58e53c9f6fbae20c6c0f89a8d40c3268b5556a77885fda704a7633e3d03ecf32d8a5999af343c0acfe2ee1cc82400e061b51577b0b1bbc54aa170ee781e3c32d34737b4de238435081d8c91bee1e5505bfa40ecf2326bd84eb9c4cfc9bae1299c81ce72c9d3c239939de0d2267f22a34c21a1ad7d364b710502f9e8644ada2d9d559956e5fa8529553f7d915b729ae1da85ac2e0e0685a83687d01c1e58ad0078d762997be688f9ad651a0c82247d2b5408923a29585f5b3f0c660adf440338fb984f3538578ff2cf988655a706efaa92a14f3ef8b8e080567279256f70df8fcd76da14b937dc52a9504c6bbc6df436f18d211ca1f67e9e8d5335ec299bb77c22a06028f3516c5e8e8efb53051dcae9b5ff70fbc324c6c59567c5e5251f07012889e68c5ff6f1879de96902783a31815e87fd4f77baf277dac4a340781a03da22e3ba2634e82a3537a133d5b18ed4887aa6610e43fa9c29d586aae51c78964303b4ea7af87c3b6b66844e87988b793c720a922f8d7011f2d89fda783361ac079aa6cf69e80c0c70ebda0b25ecd315594359f96344a1c0929d1e44584aac370fcdca10d55b8ac02b52cb612a89bd8ff4dab90602d28dbb5cbdb13a2f803770bb78175cd319dfc929a5f779df2e764879b90ce248e56370d18fc623d65655303924a676dc24b887d8538c65c29de5546eda6ffc3ed39ed4e174169c0d1b2c2daf01e0e9afe0e236feb3263d7435b313efb4869f7db045128e5128d47e7b70cd33cec509d7b4b7b7b65b4163c004e9bdeb20bc6efda1fa1c1f6eaa08a97c81a9ed218cd45a8346b67dea93cc0742bd5f8f829c7446bcbed364234312d7b8c046982a28d7652b7cb16a5088142381327c835387d9a6f12cb8afc44b16e90fd09c34030171cc54779790d6671ffbc5920cb781d9ca0066b98581b03c1835d2c4cf97ddab9eaa05f005377727caf52c9026f8f402e97b8d1f55d7665061e2429234e15aa29311e47fb8fabfb8dde59e8162ab79ac9e9dd6c42182322d9c83fe41f8c80921d627d82ac2bb862200dfb09c415b84e78c029f94e3e41fa567d6c02e422421a04284fcdddf08d17c3175b35d33cfafa3a642876c1ef47fd126c7171417b3c8b467c7a82ff454c4b4ca4f5dedb93bb9b5916fbdfa22b7c08341d5e7cc29c4d50bac8ea8af8021aa3a8d77a15cffa36e351193ae29c0cc3a4d224aad11acc240a58b765e88e03b10a9cf32e00a1a627061d6b1819f0b2d93d82b05b68698a3a4c397e45da4424c4bcd1c2f620bd8d2da96c3f10321135c1375eb8586ff4a07481da5b50b8f8537e2d647e1270eb63f03245d8fb282561d2924e85c45c0b62f36a0722e2db90f76f8efc91d9cd5cc5d8454998da1253e52d48e7fd4720e0ca0a3c72c6735991e69df5a60c21ef1c9ada5b25a7ccd153ba4da0ec90884580c8e13d7275ac2b84106d20a8ff55e122cad7e6297f2a762374c709317a9dc1bbaf078a8c48f21bfe2b66e5b6b79f3c91f88689a19bf3116b8c7875eacd728db73b84b0602c6acada813ea9037076723d7731c97baf958d769207642e91193a3df8817988d993b067d4f297a09ef09840b86c41176cf1eb3dfd735fb02e5737d979990a9472b46c5ce538128d872ffce66e41426d8b465dd7c1a7f4ebe72f99462fd0a4dd41dd532c1f5481295c5116f5b70b98ec31a7d8465ca689a229a9180b60dbcd7bf05685cb209e90ccb2df4d28ecd2151c6b69153f533b2c35cda383b516cce9988791c350aa60093c08ded9e16e894b5c29ab891b89e734af40b90e474ef25560fac0e66381a4aeaa127518c98c9e8b80e710761056f66dd8b601ab70fbe5fcce5f1cc6a297ba8caa6c7b23a653a52f5302b33ddd02ce7253e39fe5d3818fbb67be6abb889d82da155739dd4860339d33e7ed7d2aa309646bef3390f43f8e1b8ee75468f9c89c8b798febe1acdd493b2d388c5e73d7aa686a437eb364430356c6b2c7fbd71b0a60e8e1d2189d245e393fcb1b54b6def004d77526b2ca2c30ba4c26be74eb81a737427a78fd7831c1042fb06fa6a499d239bb6fc15eee85d31d9d96964482f594a52ebdefaa9216da995feb8bb1dc3af26888f6c80db2f1cec47b94647da3022609c6e6c79069b4bee5844f43cb36b74b5d1c760a0969c40bf89b655ebefdf2d7a63f774161bdc482dabb5bfbf3f6899225273543c013c05200cd75aa0eba14926682f260bba92176780e835bf62a88c3f7ef4beda9db1c74f864199e071e83592c5a22e0d41354fde308622abb0860ccfb05464a2a394c3d4880f45982e0894e914863c8afb0ff80bc76dd3a83bc9be7d1aa0bb64d0d2cd49017e976dc1fc3bbdde3f2d49ffa720e0af2be056b8b1d75520c7245df0a9a0960a8ca60a19d2bd8ffd4861826627f7bfca11825fa83cd88308c323335794e910aae99a711fbb68d35e584c940efc26b64cefcd9e12e588b8603fd43137c080bff0411efb5f9092491b41dfa130ac4754a9f6ac4f89bfe51bdf32bc6adc213882a135da31a7a707e4545d14b3f7055c82772d6390861f67c0620b200dec7f95e6a7c49c69389b13affed6665f43d2eb4ca9c6f6f40bda3a09c1c472ada1b67c2a8268adc2fef9066e857be5c4b7fd9f4fb2835b61286b0fda9564c74cddc482c65432852c315ef09ac9484b1f4c6caf464d3e3e091090826bc95c563bd362521186aa5b759bbed802e2b19f8db337d9286268ed3e3167d5a2c877dec3499d305123d98b4eb9d4b37b4589b7408805ce9b8b98d98c70ea0fefdfabd127669f04da9f073405607f29e4ddd63125b2f72bb141fdd35590d307e1c0bb1c59f8280825b14d6d5b8b0e2de660f5bc968dbb963dba4a79d5a816f31dbba6454559948fee166b0492fda112b442ffc4036a65f2269701c93191eb0362ec2a382bf3761a2613e4f50abd6179c40d1e7c67fe1935dda74de86f87e0c3ee0c5108e0db7cd2f78aa7c3a5d812afaf021e638ea19db69cf70de0bef89611c1457db8d091a07514934eaee800f4ae7cbb068d236befb9c091a84701177352e19ba0e04a54e7f90f908cf5b0b05c69a252798680952d95e94f4a62d8d69cab44d56da5a1f7eccd35895b1b5855852419bcf41452f652b803b81e39b0692c42d0a50978a9c3b1f08fd6491377a01ed0e07ef76a4f3709d799a97a0882a9e1ffcdce620495758a63735391ff77439a0bf4b9b736d9926baffbbd635da329d8b68fba7b9e115746152aabc8bb8d91257ca93c28ea591ab8823a610b611d6c0c999dc3ad5635b542036a49bf1a3a7b9ee123c9e62a60427b1ccea603b04672c472f2085ed3d1b7415a8df44c6ac52d41b2bfe7aa5963d28fe89935d37ed6ecba11f08b842c41a64b00c2b69d461df9429aceb080313b87109b13e5975e1d789e6c90b9ad5d4d2d3b1b9ace7fb1997a2439fa2fba071f07e26db3b1f3aaf87ce2655c24e205a0c8300e06bd7717d9618700e2a1625df325ee22d31128594f5e78b57776035a9b7ee18e168826ad555febe7c258c24ace342e15fec053204defc21afc7412c9b1a55fe3a27569fb32c7d5cb464a335f137ea62c9fb4d70df4e9efce7b863928e68fe806fce2f581fd6e2cec5caf5d4c8234388d455068374a29f58a1225926ff49c95a60381061a1c87199fc1053edfbf7529b8e020c72f6676dc180ab562162a1325ccd4d56d47e36b97b6b1b7d27ba7bc416752aaf13a22dacd184849e28750345f0c517db683e3bfae1111e18ddc3dc5c2f2bc8f0ea8d0a7b24d424b95d91587165a1d964d0a03a15448f938958a4e03e7d6e447d99bf0d58ec2dc08ca3ea40efa59e4c1d1f29c220b372becbb28b0bcbc998788b4d84fa5e40ef9d9a935fe9a178075bfdd7ca69400b1d862f96b3b976ce803a69c1a1ec6511d53f78c81f620e16c0490a91725e2a740bfb8bde9c9626b7314060a43f77995caedaeb068149d79f282d375a5228eeda0d6ac61c1411975e6f9a99d571edfc54a14a88af394c8d7e000ea7fa792f86de6d41a1e6574a1c9bb9f9d517a76d8a4a5dc1bac4b4be1b8115ca59c0b516ca589efba558b8daead92d56961c7325e71e61f5b61de1f4750b3d943deb1ace2136c07c04d3772faf16dbb99aec41c2b72a88b8e868f50180bc971da0e191c79aff958f50e6237254a8ca9b40a3466de5081593539190daaa37c5fac4e81e3404892d77fc73c8e87290c8a98ef28c5a18f92f19f730298f5fe274a4dfd2891be9c2fee565ddbb2f672f6758edff5acf70189c01e79b2e0b93c2d6dda011128fd7a897cf86ce9724b0dac1b8deafe76e7b973f7fe3ccc8f615a07699759534d182cedb2fa0b836b7cd6d8eb7925faff6fbcc518e4cfda5d2516e4bdcfeebb22d6b1fd55e4dff9f004798ccd815af6677a730f2bf8f42b5744a2391e34819651b6353e66003949ebdbfca4daf205a0518cf0291e91b0544d30b01eb8aee86be9e5326a7fa6196d5679836b648aa4b34488658ed31fc3e4762ef912f376fcbadfd8119614518d441e75ad354aa0f9816f24c42b2d9ac2f29d4acaac363d59ad5c412e3baf0b5e0039c8ff6757f0b1b28a4d9789b23361841399015997a90b805bfa5dd3eebace0c74c3f27ad74a038e90905dd6ae356ef72e4f12a1ade4870bb47d2cad998f01918ba190430fb6b6534c601bf503bb8d4d74fe96d28297f544bdfdc7e213f74b287788f3fae6a184cd330ac6836980883befc54e3540a2f5c9c8913450280876f271abf87c163813355a80eab5e41ed87aaedffa10e94bfbfdf2b3836b5e4e909c456c64278f8d7a0dfe85495ec6cfc71581fd02a730abc9de06ac769b8e6b12bdbe840298569684e5872c77f5b5521b2f417aed3dd48ab7b244ffe8feac3d3122f91166cd976ffb6f23834af19f79a9fd5982af4879ccc6a38af50af199a471d55d83a72cd780b22a9f1879ff9538b3ca9737e2effa438a7702b07b28545afc8c5fbd67f1370c5c321bf4871e77c731d6a010fe93faa9c8037b26d0f27dd0d30d02112689b3f42675fb15b6e00a1824208ea46f0e5640995e0c722485c0c867db046e1c8a1caa223bfa92f9e20882d03d715fb9b42b65e64176a5ebceffe1f764f5feca108fc9f2cd9264bb81d7df7340cb73c6e8bbb8f5041ce955ce78fbc719214b104c4f9f6b39abbd6e806d5ed49d076f004e624dcf29db9549200908b868e5ac2ed7baa05f58a4da0b5c5b85ab07515507a937c9bcc16d3280fcbb8c81feaaf33a7c40feeeb6a9137d060d7cacbe67ffc24746830c6448f744b9e8406427f85ce26cd0affd9a57fb0bc5758cc51f341854805a8a20d2c9c399a1c85dcab2307f0383139871fcf0617cb3f5c37e7ad53341e4fb7a3fabd48a87c1b672c68c9e2160b0e10b5510b9eea839dedb4d50514bf23cebb052b11ba6926b77d7611ee51a8012f7f5329d5313381e7454e087259b9181295a312696191287752e6aad68234db85c87bc173fe755b3f79af01e3483c0834f3f3dd416fced2ee7c5efe83d098a7346ec37d60663e17c4cf602eb3335bf61be8383f17611a8df541487d22bfa8b7a3774d63e3e28963fe02a0891edf57b027d05d5181592cf834280d45e795b7784c1b3640263fa185bbcef7cccb27ef6fe078c45441011ada99dc30270a8c1669366e3fec1c50831e9ff1601fa8a06a8cc3c8e8af032552ee33cb42e44217fe0a6438ccde7b55df55bf8646c66f700ff6f0b29126b5e49aa07dc60f5081dcab413eb852902ef30a54cfef8fffcd32c5e34c0d54cca271da6a350aeb3d3b0dbc2698c3955e35b744cbb095c3b850d11e90b999865b61fd768b8067a916d70906e2caf50f0ef7f4da12e09dd21b3452218b2e80b5eb5bba753da8c8ef12a62d7a85c38996718d20879ca6da574f9783f5534414b58eafe5ae1c07b7ee2172e35bd6253a1970049aca45b083bd05d4ada68f087b8c0345c33e17588eecdc48bd8314c665ee092246b0ac490dcb24bf9291ada652dfa6eb0e603be48904de99eb3179c6da086113926a9688af5d8a25b6b5000f7cf6de44956b28266e293c15d69409b99a865694333d511e9b376885857f934a08b869316840da334c37e82c015c8a48f8f2d8707d730dea2829a32fa78a02721841517f0808aa4192f7d7d66af53bbb787dc5a63532a6459c34b9a6642a92fb920f01a3350a57913cd3d0ee9ddce7ea910fd6c874868b4075c064bbe132d5457a514bacf8052fe327e7cbce0eedbaa7d1d96fabe69879a279e35773c07032661302852806a81a7600164097ea2fe2ee7a59ffabfec316a0c29edd3112ae11f1ad61bf5af37dcec535beaef0a432226d1c221e9b99f95cff3822acf03959910b8a784e13c078ee808d502f5b70c91bf01e6eeac8abdcbe7fa3af1a6da3603b55f904c3a775502aaf6adcbf1870e42c85a8e65493db3292222bf14e688cd6e4fb4dd3037cc23edd9ba5840421bc86e62f3cf41b7de47d2690581ee7d33603542dea464021d466c2f60dbaa620ac571f7d19f4c846d0e6057e1c8dad75dcf9623b05d4b73ff9e58ea89bd7cc1f1da212a0ea8bb98c068c72077a17efd3a699e10d852c72609a038e71ebef071527d5904f304ea683bb6a13c38264dfe4248207131a17cbafd3f9e6dfc26a24224bfff5d0e93f469ab070cb8466c3130cbcc6570ec865793e274762704fcc2e14b75dfbffbb80cdf7703fce43d91342d19cc54b67507bd638798f70535052e7a14e1930e278deb66cca2800eec8759680a85763154906eced8080603aebe1a08733e5c1f3eb4d08a9bd2ea7b2ed174b3eab32e8a96777f7cb4c0a9602727e0f6533e02fb47adc415ba3b8464bf650a2e60f698ea925529dda2b544dff4d247e6d8f0fefa62d06338a59e520eb15b95f9c67bb8e124979113170776af37e8d42d3138a09248791ea5e5dc312984e67710a82716227504db1a4501fbb1de8ee5146dbe665951855aa209dd46df239352defd6a82cb023891df5b11406779b44e3a96849704096b2f253c033c2dc73f88f3954520c623853f633cfd14cd116385d6a6ea490a51df0076b2f90dcb40c6e50ed69607a581c7031b540afee42c607bff9a242fff9696cc3919ec89b289d9885424a0c0e113bc6ad2730df16b341bb822a416fabaf49a1118f1188999438b626e7cd9ac438a960bb0fc53fab18000b18cc990136155ff01a4d5bf2cd1fcf22e5b87cde9d8271542a1aa3c878ca300004c82a3701419b87589ff2846e7571ec57d220be3ccfb871584d64db1c07fec4ab2c6367efcb46e91d62e3bd505df391eb0a6fe61bc988632dc714b9c8e14b5efdc226033a6770afb5715cc03609fe7df8cf5da16a7e0bf643d2da4fbf353d7a13828f9abe91f95dd83af0dfc938ce968b332fed42653e79c98861f5d50863118632b6d5c1bec28a67e617cab3c08d962d99ad512475d8f46cc303b73fc0aec517c2d36274faf8a6eed1a9104c7b3626f3aa2c9e2f6820ee973516be7ae9c041f032dbec0ec2d91f7dd038e40dd6f4b7e21721555a606f1a5fb5ea4d94ba8d0afff2954ff3c091d41bb8c109449d97578775bc037ae4f937ee90cfc97e49a335c56cf1371268dafde655827149ae1972d91febbff0ff8539e818ae0b0e13f1491bb0e2e7d5e9d9109ac20bfc46631cc31d212f088661be5e791db047d88b77b00018c8efa1014bc8c514d36109462272ed1bb5f667eff8e72d7231bf40149c54a0c6c2ce1d4039abf6f5a97d213485b49bda7d11aff76ea79bd31c4470694a98c48eb9a4ed8ad8fcc6a02b1021533a2ade1415727db584d7c60bbac26b69d4f157998f6f12ea362c61796f01bb727bb6322808644fb62a84d0388fcf36cd02080411371039172cd3d9dd8ef798753b9b0d3290777db63694beed9f522b5fd7b192d9867c1771993f734861c05decdef2fe6a828a1ef4cc15e4fba26c219d7e405bba4f045158f24ad7755bf6ab954ba2e3eec81ff25e0890efc51955fd3a84c99aeb0f9a0b958a10c6f0339ac006b4953b3e37247393d261b97d6cdd64b88d16916f1e7d1a4c38bd53a35e741bd1bde180a6f1c101b59b74d98ffed9086e803b74e08f172dcf30df23f7200806a55cd0266e9f34958b4b195bb5e1c028b1bda7606fb25ce29b9c2c6c96d811bd0cd115f044a3531267aee78327bcf5136ea37bfd0d3eb5aad7b8e71b8e612b7ef26eb60eb4a4732e1a5ddc4ac0c2cf62575217bf0dfa1eff241b619dfcdb7462489e8e1fd841909354c99021b90abf008e36bcad460f516196920e181c9d36d0988eb9b6f299e1bad405e0be22f9409cbf71dadd63a1941359f91eb54a23b2aae2dad93f0a8730d6633a7f7cd1433a3396270d345d3e0a138bac7a93a116613a5409f4419382de8ec478a0a2d8cef5b7e8e8eda1d57311f433bfd706a0608ed542b773ab85de4225c61abdc8d607291bf32bb72aaad492e5263b391280dfa9b05abcd7ce445f59503a8f849ae008eed3a80de5b7f59def3314398c12cf881e02bf4be16c118fcdeb2be8aff88500cb46a3eb8e948942aacce30590f5d292da4584d7b79ba18e1d387565ab176c70455e039e226bcdf4c0a23e482abcf9a42f1cd5a4633ef4d1f8e2c9ff49ddf89b673c030509883748da0d167758878bd96a9e18408e2e6fab3f383d3a1db827cb55403943173fffc8421866097b92ade7433f23addc0f38b1fac9d82e9a18960fbf988be027d76282fcac866af0e236416c8c6262a86d944e185906e3948dee9404603e2db7284f5b09591126e6ad56977f0565b0731a3f21b83659eb9d2439f93974686197eb5ac174b4dad7394d993b7ac4f97a295517304b459d1842c0dfd8b9d16f6e8166991f94ef668a686e0b3fe1c3b344bd85ff1bc838d45635230b4235dd89f2d47d7d83746c1c74c9d693b2a4c9805814a4fb228640d4e8adb2f8d65b711cc5d1b01ebf34314df978ae0f7e56d6b74a623d1f8f639b5e8a3d67419563e380c55548f4d7c00ed31949c68e267fa5378b37b8b8be8565828bbfbd7bd0fd67e5e4d0d5bef8ad92c18731767c4ebf439520d9a2677013bde21965be9bd3fb3edcd45e0baa250b3f85f1826316a7c573c5e1edafc451876f9617283e44cbb00818e295ee3141a6fedd2b3a29c422f1e220bcac07458656ced6c158ff626182ff44fd35616cd2a42ada82bc98b2ca51e8a48e2f3bee3c408bf21954dc174c1e684b7f0190b7b0547e48d3a010e839d85823dd792b5ad90766942f260ff8c9b03f00dfa98a1984a891c35836c6ea8486af4d4bfa11fd7fc1ca1bb2bb35c30116dd49ed7758620ed9caa96859b67755da6980f645a822a8e9d457da0e5604de3bc85ec699d32e83178ee0445610e2e5fa45632ea9799bb5e0eb184c872ead9535a20d6b54bbb3fae29d0b88f685434c66ad731b991222f410f673156568aacc36bb7e616ce9afb7bf4e10b009dae93389e0b1daf2c9c7ce4ad198f8ba63b3c14e395e755a34e3012c0e7ac0ac290a224a6e6dd4756e4729614fe87a8ea7f6139ab24c74e8c45f36c812365ae3de5ac725f0ac138a4ec5667a3202b7fd5b26815ce9ebe81c607bcb6fc65d94d3c0ba32e869cc628cd160d755123baaa2705509d93129a5b080d5d4c3605044b14532349d696571f2dbd609c9138376d35cd8ff4b5d4d5f64e4a8fc3357c488d567bd8a95cb3c7098f219d9b0843608985d765fed9fc1a471b3cf67164a3e0c9eaa5e4161435b1514ce06615d145118bb8e8d25e69d28f95d58235d587c2f4185b87995a67601d5336df5caeefac0e79be2906d6c4fa42b3406f1354d4ece7899a99c4bd293127022e55b443e44101016f30dbb2ccbde0e649d461c02556457bd52d4a7b2618acde9dbb2348ea52ea92da0e5789220292e08c27ffb05b8ec3d9f7c2759f311a8be068386d3cf3d0884db1c4fbca84e35d2c8a323ebad4681298fab0e1f002ff1bc3dab9d7256881ea984b61d7840809fe542e7bdf6128c4adc57ba87095703a56fbbc3dcd085aa56181ba72dd4bdbc4d083fea820e381b994449a73bcfb1fefec1fd476634aa7fdc1ff34f00eb18c36f7f4bdfcf9b4c3bbe5a2606fdbb5e11e5d4796f16f225a933cbd593314d387787cafa7ea5f1b5c9d0180c23310f6021d1a1cf40f85937960c88e7d30f1a3162e6f2b5ba9c7d11096c6e88acc49cc1c7d581e9815dd110164eb99921d574a006c5c2253e5ae9f9b0453a2bb16105d936277bec5a8d592b4715d7b1ac4bd1c9139ec34b951a86baa8f3883b5396d5e0e33e8f7f176180273f603b6fa86404f1f1c53a6df5578939e2b499e24f3c458a65d3f699f100f29add6bce79fb97e07345723c7f30f965dff4525a82bd4db27b213018617a9525ed8e3f9fc351f9f643a5e3692bc6a006c82f230f3da6fae33d112a09ab530f27626582892ca9a37297432301557e2bd99e73da31c3a21e219414995d7c729c0a5488eb0f42d8f251477708c1405cff5b473ebee8d5ce47b59a4c5d9be7cf223ab1d2d3dfe428ae2e33f7ff74c708049d55c0aedce4917d5fdd59c017ba062a84dd3dfea8a8a459b3e861ec2d5af73360bebe79c22d111444215f1ea9c82f772c36a9295f351f3f00654db37b6c441a23f808bcc882b80c3d0897862c164b439c21125a413874041ddd3401b8a2d6db2624b1c261185fbed1d19ed2b15fafc627992542ea42a09bc84dc168e3d6c85deebb8c5a6d8758f38618b2e0a301fa794e9bebfd986ef4a8df9d489b748ad83ad6cd33d138a67351c58d10880262d18eeb5278cb7d5f12f7fb3d905347d6933acabc3724bcd8e9f4de9f8b80a909d6aeab1484cce81cf738bb5a3b575a606166262c6c66d1b39a2b00f2c859b0ca8aa26137804e8d2c0c175ffab9b33cf76b019d0d3091187dce4abbb6cd0b6df5239aeb7393416587afed55206aef9915901c178a009c6d3b7c4150b3c65ca96856649bf57016283734888fb07ccc56a6a9df4ebb3d569c6e07b1f64f19f74c32f9bf6934f6134b6beaf5a09cf910b6d8a1d61ef9ce799950dae80f7e5731c77d2e1baa10ff849f1b43e407b8ce8c5814cb59a15c30fbcd7e2f8ebc845645ca0c6529952b06e0e863f819e56391516376bd3a62e3364fb3f5b6f92c08e16ff172f39a782fd5e88f16f9130904df060f7d154c017a1e64695e9a81cbe27a30045ddb52982c47ee49a9a965712a309a40296c756f376c126fe97e7af511dbaaa4e5bdf71955dfa878579759d2de4e1f31119435ae399b959624a0c30e68843a85a69f578bbea8bcacf62494ee8b7b5fedbdc24fae6bdf381902c09f34dfb681992119c97d93bc0a391c3ddbb08c4497d32b7981800feb5841940f9c145c92494b1a17a00eabd7de2ad32d6741e340bd55dce8c7c6eca06f7b81bc4df1e9ea88d0c260699f4316adcdc7e6801cb8c12969480d2d6a15db2cca2bcda23078ad50fcd658666cc7573031dc837d59df6836f02583ff70950c495b82c8ac1c7c1e15d9c4c83ac8fd9dcbda77383bb21988ff75f249d96ac550a3127e43ae5b30c91b32d1c9cbf16743201a608f22de3157e53f1ab300deaa8e212907c0497484b65a9d026b43880b15ff1da6a3d021abaf78ab90b751a9835f6fd7634ea1c82ac1df9e8c7267f2c1e506ab1f488a1116eeaacb907b17dcfad8fb58b902d29e1c2ba3ff0392459ff3d49d4896b57515fd3f71a475aac33bb9b96e8ac0634772443137a30c2ca07bcfba0a940a87f399e1a561b64169efab3dc53f64e1c70595a266526a8c52d4b52280186a4b66313f0451947ffd9b8b2665949799bb5f2d3bc609defa5971e2b12ba745780081c73f033063c852801989da0a7a8a206c9a4ae27ead2bceb5f4e771ec859f31cbf521ee983a0a027a140034ad57dd52bac4f732f53818bb0a403f4ed5a1c99494a78e49d620334b85f8ab7943c8cc5bc6a6e856f63792c868afeaa6e96cf8e813cfefbcc2a42688237d9f59caf00b630855575db63128e22df188ddc94a648f76e1d60a75b297225af07dbaff8ec5aa8458803bcf59bc68f61d4eea912d8b99ed3f1fcfb7598a1ce4b518a596571f42a1dcb3b5abdacc3b6ead2c0bf172faccc1ba7ca0405597f0630f7a516462b96257a787353d2bc5f50e9230fecc889eac90cec46378f356153e364f5bf87a32dec24f0157a3ec3d4745fb0cd97a5338f87e5068677a29461cf22b291ffa7a9521eb665a5ad78323a251f0c5550c7b01da0c29cbeeb2474a7839c6834a2800091da24055c7276e18ce55db6ec855c89a348ffb9e1da7f92de17158916c221a491e7406538fa9b5f082765532f438ffaa436ae0acaa3da2bc7dc9e1d76e95e6f088436372d41905af0d4a5c0224943cc0cdd85258a734febb44d7dfb7262dc7da1a153476ace584f45344fa0cc9c9bd34097730a568557fcf87ed1c403638988f70b0ce6da0b3c1d6cdc7a8c11f28fdb885bedd8152f2161465430a95f75f463fc3c463e464e7ba35a70a9384619f674bad7cef0e49012975e1ce4dcee029faca22e0ed76d5ea2662a2e9f7a451a3e3a3385ac55482ab3a57556af3c5a0eafee4045d4d66c5f90d9389f3f571d8dfec0ad4c7d99143b7229bf74e4b04f0b36981aa17e273f91d0b5d51aad4947e93ceb35353828b99712f7e35f1db9cb835d24a4fb6be0839cd7aaefb89580820391b91c00a2f7b613cfb00dd9d43d45032af804c4a71490e8d3f59926f7a6326257fb8c4fa3534a22271cf41fa0ae17769ad849fdd1cb32416e48652f7d62b0e9a0abfde61d311a45f1169c22ad34ece347e9aee14b086f7218925e2e6cc779deff49b289d10fbc06219379edb84d09e6bbc14b8f24852a62262d02ae6b589de245bd86f9e94970c0d3bf8ad56a518ede8249868e0d3d3884c0cb6735c7eb65ffa991e165a55462089a46cc6774acd35b6e66967d9fedd1e646f9a5cc21f83a706c8061cecd88ad4cbd3722539c6f41fa9aad0e1817beaa9dedc1bb71b50684c85650a850b0f10aad25b6a73e3523592ebd2a6482dfb34f1340ebb436474ff491529274de67b009c1ac80d106f83a8f8931609474a557c9fb6f6bf1468a2ebb9057f54121c841961deee14295e1cd676d4fbeb3b992158350f75555bd25d7172d2cb8b33ef6605d5f8bc050e89796c8741efc5685f91ffed847ce886d95d65dfddc3b1694dd33afd18990523fe155a98b7d8fb1872fa1a89aa91062903995903d2aac2650bb62867fa59f749017be18f8b07d58b30091396f26cda2220c09ee7fe189a72aec947e7709f4b37f7c5387df9897da57778b06e0f81bcb9970a523d3d33e02371181af8afe0c7e5f70747cf229ac8ad55709fc758f3cdbe8d6f842c3437f4f1ef99bbfff8c41b516690615501300516928ff1e832f2a30d48d5771d5a895b330238b174558e64a241fdf6fdbc3f754a714adf714a87416a787de436176c411257127036ff5ae3ad6dccc3537791b97b45b8b283fcf4043a779da9a5cceac40702bb554e769c15e9004d49ee08367682efd6150c5002769421317834705b6882d673638d934b4ecad61117868fd0ac15ee7306c243cf052b859454c954b2588d0733afae58c50c2bc5736a5e2759bb12d4b47825fff0dcfc9d95860ce9149105289c588b1b17653b22ae3eaac773da44d9af92d5b4b35d7f6e59b7957f01999cd9986d50b89395c411ff451a106797aeefd88ead53006dddf4a2632444615ff57dad5a1fded7d3da0af5a4c54e92fb9084d8b3451c35763adfbf256cb5400c7f2afec454ff8ebbd9fe3daa8cd22d8dd6fd3a4853ecb6a9a4c93ae949291bc9012b5f816702cdda4db198aacf6575073fb81e5c6f89e1ad1fc4142fc62c2d87f534d209019aae8b0236266a08f6325b85ffd61d5ee224e17ce73fe9d121418bee49ce9cd39c7a7ec6c25859ab5aa9b1d066b17be77285907c706935201084589a179ecd86661d64b4e48b4a99f832e3f8c997fa3ee3c63bcca97b344a2f65cbd9ea9828f70bb8f4e1828651133ce8286bc6a0a69e7135f4f595b4c44355b5642122b4b995820d30a011d299bdfaa0d2af04e091ec752f9aaab8213d8e3571795b5f35ef4efb1b8903aaf8ca466ea221021960fd8624cd1c4ae66bae156a1e8c8b12c38081a06f3dc0dbda709a3356ca7fa58fba0c9a1d88dd067f3c972758988549b158583d1259c027d97891dd84c73d0c944a0654d75e513e0baafc3b921911180b2409b36d2a7254e83374cab456cb30720fa457dab4fa6a6cf12d07d9940534eafc947e4c6f2061966dee5f0a7b80fc594e6a04925f5dde80056ba31e8c1d643f31438a0f1e57d79bb9c6fe72b5316ce5509f6704c100d7c03a393685b9678051760c66899266fe86efabd886cdfca39cb8e220ed1b9543ef8d4193e598c276575cd504563a74026faddd16ffe857eaa546055ebb0e5bdcc51eb14caf894aedc428718728fe2dca0ad82e7c5c55626be26bca22ed507cdb1b4037837eea31286e8239ff3a9bdd9d67da4842cfe785aaff82d477549d25dde2138c7932df880c8636a7e35e631e8ca9c72b2be728fa56f84a71adc56e1f1ccb290a587c033f9a092029fd57577ce40decfb2638bda273481ed9ae92178dfc0e42b87e7fdb34ed3ac3d51b52ecb17bfcd48967cb6cf2e8a497f07984c1376f359a2f98aefd1462c1b6f8e938b77714179bc0a963b964dcc830bd9b0290a190321bfe23404d6a0d72bb64ebd82bd0178865fb443373e00ec902dfaec59c9f0132d2821948ea72408ef586f1bc3ebc158793723053fa5443ef08330879bc4be21188dc2e4b7e0c1cb8d02d0072d3cd627f9466cf871a5a12f49f1ac41cf36e75fc1fd009ee8961a1acd89d3707245f48a1f4e42c60693f5e197c267440c990c7bd3a7c48b3e9579fd0cde62a1bc5d3067bd5d80eae81691c3cdb6da91f8d23da1f3a7f44dbe322c894d25832065d61b46c61a19e4f996738cdeac50bcf5466e8dad409a3291db167076519385d81246e22c2475d730546caad65534c058466fdab90ace4701955dafcb8dfdced042c5c3c58a7433f437fbaf1c944f0721c4fe0e0ac5c4929d7a6de2ac7d2c0f5f40f4c01bfaa8602c8021b0b6d9efdbf806b608078f729237341381ae7a96196464242a4dd4214fd26261ea7e3a2633a87d958ccebb66ff079711c1d6095a8b43fb0b0c31d6287f5f9f24949079ec9477ddd1c9844a0c547916288f130d088c33f9592101668a1bf1a3b421bdb69d3678caaaa2a2bf152cb572e3622cd1cb33b69d10e7923564932638b010185b102333c6a7b673a6773a40736bc80263dde4ba914ce1d565107e538953698643baed3d870bc5e14488b4deb5ec5e3f85833b14903af1b3e7a717884319d39a5939f489701588887d5848427785921281d07a2857aaf1482f093a6f10d1dd40bb9874b4e2e68559f06638c57bc4f8c950711fc87a1288fad27e2559d4d3dbf23c652b2e4b066626e5b7d6844ae50cdc2a38740287288dd3eeb54b405513f9759b41e2b668df580eaaa954c17b6500000031030000000000000000000000000000000000000000000000000000000000dabdd99f4373594543327d2ba09731ad53b82798e148f8e52f45b400da12f0cfe223507022cb49c0e3621672ec1b21c35d5e910908dd019a7244909a212930e37785921281d07a2857aaf1482f093a6f10d1dd40bb9874b4e2e68559f06638c57bc4f8c950711fc87a1288fad27e2559d4d3dbf23c652b2e4b066626e5b7d6844ae50cdc2a38740287288dd3eeb54b405513f9759b41e2b668df580eaaa954c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff888e74badc333841ec4e4ebec1260579e7c939384463c7aee3c376ea3ff01318c30a8f379bd5badd7d0c4751aa55a1ec06de03bbed9c42844fa1e6244b45b27f2d23da8026235e78520c47abbf48068ccc93e4ca5efcb0ca2bcb6193630552a858206600000000005720660000000000eb3f08000000000020f83638b4477a208997911e3be041d7f6bc282931f1eed7b71ed66c564c8cbb5df393eba883573170de382718b083760507fd33cdb69043c0423aea3be5c8c03f6a86d412242da901bb16fb96da3155ddc579142ce1c27993087a7d19d0bcb8f40000009d5ea643161b236267bf402c3bec1016fdb94b1ad556dbd49aeb97c727434918336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71d8f65bdc367d30dcee29b756a60fb2421c161c7411c58fd836cc3d2ee80e80f05a84eebf438d8caf71cd08c28dd325bc091cc6bc364b8a0ac5d13a9ec1d0c04d388c818ca8b9251b393131c08a736a67ccb1929782fae74f27a521af81b6ab39d6b8b3788c06f845164b9d6831041aaf2d8de8a0bf7ce65e00c1fa929b1990ad521a00973f2eb859ee50f89dcb2d4c5a33686ff4506146f0451088c8da093ab9ba20c265106b6230cc767403642308044e11849a804103c8e0a143a18d707e8422de21b50a61d1018fca3a0902616022106d29d0d5e883296c486d6f3c23625d364225b889f002b9004498802cb7744c842ac0989b250901125695a184a231a5b8212a45d1891811a88c450192d110dcd23b211a83428b748a90393c0559456641061027e283cce53d040288453410f24c7b00398a314b42c9c162586e1e50ef95b404810de20895533e21c35e2c043216e86122d18f361a09431e45a414ca3646148300043dd2ed1b8d62f0412339172407e8405032bc090f8c2d8012cdd8c04683b8860dfc9062c559806260393c3b28c1fd11b8361e3e27d3d3ec0e4f0f0c5cf59dc89f98b6783fbbc117652d2ff3982fb039e9300b010000000080c3c90100000000ea0aad00000000006bb48f640000000038020000bf20313e03000000000000000000000000000000000000000000000000000000733447b6737747c6510754e5fee8e1cecb5635a53d5f11ff1f821ca71713050c66d73934b7db72d971a4cfc5732c75d1c056374cce18d8bd3b4bc4e840bb93d8307e4dd710e61dcf9df75f3e55794097233f8d91b6d9016fd09341774d4cecd96265617665726275696c642e6f72670020660000000000ac140800000000002c947b446d8550e44e3205eb1ce66493506c5ef2c48468e821015eec7a89ba4dea09d6b09b7e5244d5b205a3db597aa07e6540d8a1dda28653c6dcd29aa4c461cec082ae5243d4a515fc287005dc496c053525e49f34acf7819b9784d1da4ca2f40000002d2aca05696594d2ba9a6a6f45cde8f303fe3530300d2515450f7fffca507c70336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d7163759af08ec4f3c98fa482c76aef2b9768a1b07b148bb5d89f37ecb9f7f14f217fb2d818d154b3f5d504b716528172eaec2d3dce07fc499e5f76402722c8b1ae1f9090aae28b8a3dceadf281b0f12828e676c3268682979090c825df91e9f078a7a1e943f121f2b8cd5bdd31efdeae838bb4e4b97ffa52f0a0e4881bbdaec1fa63a9e450b6da4f03971a28a83317ba6eb600384d05e155ccc18446cd0c1ac6aad25054211063740dc6024b1223a15046e74a6915b49804e070d207e002314e4c215b191052e1cba8cf2abc8202642068006ab382405066aded238a086e72c20cbca6b4ae80222901a4c2098060106dd5e023129adae468219f0e44f14141909420210818f41219700c4f5c64bc58c81282dc40014910d14e02680644057205424a2a0c87900188ab790102bc0c3106c24c3b00208a2be1624d80672080262cb4113084622d6488004360c5ab09e7611d1cea2849e19916630b4ccc01e48084022c4e56428851727f01312276491d78ab2461e0c09110ba6f0016089369cd32008144022ca055deb0215a84460ae811f308196e24485a9dcfd30343180e17178562d2c8ff1bf0560a5edc2ca6162dac5618e61dfb92300b010000000080c3c90100000000a613c5000000000057b08f6400000000380200009751942203000000000000000000000000000000000000000000000000000000331b1413a14ec8a05fa165bd21983718fdb7d3fd25d4564e7af7a930c89bb75cdb07825c4126b37f5a0e736d52d0e97772e7d6de35f93147fbfd676f3135e2ba59b6f20eabb865a56777ecde2ab0c623bfda3a5038449a6c94ac934bb93579df7273796e632d6275696c6465722e78797abba4da96406200009070c2a0ef25253ed8bde7cec13cd1c684bb2d3fc5e348e075b9de90db39852dcecae442b1427db9481fc33ba860512495d28a3968d1be873607bffb93561cc6bc181eafe3c317c1c3e6450a447d074992bad87b43b266130e90d2c397b0e973a9ed43993de1a5257d50635eafa95532f0e269831ea9e00050852a803088e27416d2e1b4cd40a53c20660b1abfaae4e991d353d572b39e18f25f48f104ca0e645de84054b2583fb21b961f31fb9ff496bcc41476e4754cdc906b86e9c6d783b68e800606ca467ba90b7b6f7f4e482c6e4bc46f0a5839019cf2c497f8fc10ac24f9637f11a72dc573212505688222978c8750c09c6019df77545f845611334ebd8a463c5212d471f9c7e3a5f46a7addcaa29f8558b5079ac4cae9604e1c798f839128fa8dbf89eb8cdc931cd00146140638bcff81966099614ce257ee02529e3b8c986d9716da0f3b7f000647c7afb829a3f2d78469f420185cd7080e41bd638164a27246a91945a3e964c7e1ee5da26a4c15a841bc63422cf2d24734741bf740a11725f2da781d2e569862f067188a168fcec84cfec11476005c2f21d5aecd0459531bb5b2d60b45db7ae73fbb619305b8c22c7f13d92d54011ce7ad9cd85129b36a09059fa4ce172c3818bcb690cc1cdd785b989c025166da87d38201803442b86ee383b4b2716c7fb80177c5286ac5be08823cb2c100a7c5de79f98895a93da644691e96518b2a1be89a61816df8d8b7d17366927715242650c74d8318cab49cd8e1409c8901a5a69c0f38b3bcfb8bc3355127008011caea61f0e646c109ab89cb55ffd351f887d4b91efeaf45d7550f15951de50e184157d8837ae39e8383be6ec4c808bf53337065b907dc83a952b975b614821b450f20a93324fb792c29144e79b0e030b8eeeae14da1bdc2ce68b5dbd6c87bd4b2164156a23e7020096c90ab3b31eec4a0d3aa498141ce3fae7583c183fa35a8b2919299d148ea56b51d6382e3e96ccd96d280615bb7ebff42d9b3dd0cd6996aa7f908ec2f6ef6a7dd1734871e6d336bced67bbef6179bcff6f4d2c4473466db949571bae0b7521f8562b8fc435ae8c9ed44b786ab1373fb784e56831e155c2c5d957360ba6a4f8a646e5470287d6329847020cdd24730cdf5bfaab0e9a68bfcebe34ba049a28abbff91adeb04545b54f369de8e6b144c728a88142a6f72288d7c955801c7632a3fa706a192dfdf21d972b3406eea28628367ab3257e245d6de1db386f66d0d818f1716b440784b430e75a742ea8239f9580a57851f89043e8ebdeaa9350d4cda926e35974f2169d143500758da678bafffa455386269f01e919e0cea03160c74a28ab194432cffd3ab951716eddf9eab06ba0a3a241dd6a87b4710b98f06d5d9b22e35e4e8c103fb80b507635af839fe042cb6824b24c76a5955a192fa74cf69ba35d5b869e92da2fa5052364fab10d1e446d41b6dc31406fe605cc49bfd8bdb2de076a9462b953e2b54991b4115e402238f73aa3ae2e855632fe15501d520271eb87daf721af0391b6f293684b1944c1ea392a1177f6d3d83d36a4d806d4998b242bc8697b4443a8c79304dcd21ba1e1d4ffcad174a0cd646bb7bb76309f837b9e92c91fe6da6befc837cfa203cb34064cf6391704f2d342ff4e8e3ada3106aed188a9d5716ac9f2bd40c403a14b86dac7e5a82fe9bad81b5877805f44c367bb6b671f14b746794607c0712236800c679fc32bf8bc70a6c5a7bf27faed06ff12a6a668e231334d4a7a6437c04778b04e28507b8d4d7db6e88fa4d2b0233d0387ea742d436d1c6e62f85166b85fe1d0846da7394fe237bc05aa13aa6a6d142feb7561ba350a298e36c9aefcf07abfe85024905e6cef6f68772f2f3f062374b49348e14b6fea4a9a502b2dfa53e9a70ab5bf798b4f48f9b3b9384912dfcb7c754ed6aa19a54c997d8a064ecf44606a0bb495d6d83f1ebef5b83d169799711e481ecadcff9df942edc321c8a146048d77497ee652af270cbf8e35498069aac6751cbb8dbb275a26da51117027eb20f6462d230907c609ab78538ec582742aa0f7df5ce5964c942d134a76615e487a236d9c8ba2b9565b7727f7fda376072ead85b181e5a50b204cf0d687813197ebde4b2db564e5c4378d5c4ed669e9599959a3661b39097d10aa5371b3c332b5c346322cc62b640b13e87e79de4b5fd767c8909274bf13eb7718f4080bdd8a09c22c395da074c80723a98b363e9c3d4744fe0430bfad06e0ae596fcfd1131c8a6fca08b0a2d496d299786fd698acb41245f9f7c27ff9d8afe063431908c7682dd30a2122c71b782638a5f87ad8ae04d3ebbed5ca3716c024d995df8b7321e53b91431e408b13992778909dc6336c7aabcf664ca27f69446c35aec2abaeaa810b7bfea4965932fd691e72baa802fa09d0375264c1480d0b5741db92c33d27915a7cbb5d8eefe9cc2af0ddf11494c9411151b7040699e2a1ec04f0c60e0361bbd83a96ac616214d872998f3602fd7094a5e5e9b221148e4007f3c0214ab5ad507c9a7b38540208c3f593740e5466988d1190197ec0b56a58762094103ee61ca609e189712d821960701ab282698cdefe031352b45eba3fcd2debd025dd64d760dfdc8c4261acfe886fbfd42d06b62f1c6cacf44abde5f12cfaa53d445310785aef0d8d9fd37587bed2fa849485bac9373fb8cc0bbea33178fd8bdf8283e44d1adaf0ecac08ae6130d0e7fdeb21c2d440ca11f10a8895f2781591ec6fbbdde4e4b5b64b5424ec198acc1024c9fc6560250f6a139c85e4632992303c746e63cc530d18b34aad2c561689341f135d1f802820844794a3f21adab79d01bdd265f5e3ca92594dbc2aacf51ca2f1814183b6a3f83a1909cf153a66386f3be4130812bcaf8a44e8dce1c978796657c12c40a0de05f04755f1472d7a9a6868ae82800cc3f44e800ebe76932669d1390932ab93fb218eff814c0248aa51340394ce456e5b9d30ac85d6e7a388b76373c9315876cd589215bfce100ceec5efe2a747509109f09e51c40e41b7ab32a2ba661859e961e5612bfcba706e61420a86e0255fad0082be735a65386e44b7dc73bf7d0eb4bfda09e02e14e8b5892befa7a7fccdd53130b16d0749bafda4f08e3a150d065d48e8b0ee1eac644bba97fecc7c6d2b7b7c261297e97dc0f9c97f43368ec1352d475d67c511d51e26e043f1b88b54584162926f4bda52005008be3d0bff6670b03fa635b4e78780d4b9830b2be14f6094e70ab11618939af5ac4d3bcff2c1d7dbcf6539bfef8fa27a642e3a53ab0faf8f5291110bd8e71417fa5ab675bdb58a0a9597587a036fbedda57ed96f9f749ce5a09f581446a3264d5981ee54eb6f25ed803b814d758145f65b891aeb5d334d1c8d4822e85cd8110f3405892ebf77e0e3b9e8922fb35fd53e84f0e5d252e5561e2ef93738e9dcd6ba3a66a5a6c76c33537f048ddd678f9e1be929ffa810838b5be2c0f7f877f19a4a33e96bbd7a1edc0130383808b06202a039883e738e0c39fc4a3e9635acdf9e10bb754be2f2a4b8f7d724ece94ae6774162a1585257b102ad43b27d980cf650afa8b4e182ceaeea161e0d34e0465a437b62be24d61c5f5359c40ebc6d23628b33298caea2b2d08e3c00c0199ebe0ab3b008b352d8456ee3fd25813522ea01d9885a0ee874242fec008063b242026223ccfe83626a9f4c65f9c3777ee188cfcc71ba72cf8c9ab59cec204ba1f6ca252fa84171bd3a44e30a684aeddfb8b7c688a29009370129a3b05616f2f46bc8e363cd89440f4cfc405f78bdccd2b7d8cb909c7f5c612d03600c385ccff1ba8a4ea2cbda8f2e8dfc8020d9fc3851912bdde347f88f6fb08a1f04a5000e5e66dc9573b407b2d09336fb4381b440f8d879b2cb34554a2fd543b94a511402a3560111f1e01a84190fa001e3101d3fab1c75e1ccdf79b34a08e372ee9ec926fbcfa210da999fe471592c4a64a52894c27901ff1cd3ca60fe8b1097579a2908444927dc5fe9d06c1fbee16f01fa5cce04bf460136de368df82a71130874c9d7fc852dcbd9c4cb639609e56adde7730ae914f6f33bfa97ab9ca2b538259ec9c48ca63d6fcb2f29d2dee844f663813eb190e6b70645b7cafb22eaca7f2afe40cd0423d0dcc4094b1605a0d26e071c420c912eb89a693a0887955491c5938ff7640354cc60ae12ea98bca75c90d548ab712fa49cb0e1a1c91598abb91866d4ed7d5991e169df7f6f03df4666d1013b07e77be4a1f975a8eb1d6152dabca630b6f4c4dd41098afc83082019d7d4e07ceea7e5f280e4d82272e3826184b0033cc098a797af4360910b77b653cdcb095f98c04b4d513b6d2ac92ad8318f02a0cf91866dd82ff3b91dfd46987b8aea4d3d45c4371f294f61e3a8c0372aae5c0674354f6d865d705adfb183216aaf7a6d0f78199f727ecb8b25ad5640a28c7faad36158369fcbcdc855dadc8514facac668cf409fb003090930a65c4e2acff69d63aa3a93f4d912e3fa5bca8d7103b0a43988b7087a27105bb34b30ff536efdd8c48e6af13f9f20fc40834a5d38d567ecabc85c9897e8b16aad44de3ffbeab54b6464bff1b8d92bd2323a5f68dc9c12a9ec3f7317c0f0538b5823679a9fa17e0b5254a351b014e39cbcbd7bc773890047f52e579f27dcb0c3d949328f53045430d3d8c53e953425286d144860f36aaa167d11b4e0719fe28372832345500762b4a626ef7706b119cf23dadf6365fc5c7f61538970831120c35ba412c666e0ba03dda27685ed9533b887ce096f9f58cff750bdfb1f975cc6a9c1781af785e34dc779f723c651d09e3a4647dd945e1245113dc1bcee56231376eff3a54b0d1ce3208c9a0e60050effe9e22a42f757188048caa9522e0505be1b50070dacfb04ebdc546a7da3373eeda5453676681779974afb973295f6b5b5822ed917a10387495eee669bdcc20b5f9fad4add658fec740ba1692b4968e475183bac196ce5e27d3ed9a97bc045ee3c3e2c0b252853d39eb193d8b35f6050f50b20942dc599a06b2ede62c47901ad270c9af2e56ef2a69efa42d4cf88bffa41ed942a9860aefc4ed926482eb9559e8aa3b4645b8eb450e8db70b0a40f27c67f147d195ec9b3c160918b7bb27cc010cbfa9ec94406659b66110495ff2336daec05ad62c64e5b1d7f40299ea1d0ddc348a551f309f1a1df6887bbf29a05a9b5d790d97a4c11b63ceed45090689b616f73a6ba914e6e3a217cc24175e59a401c89bc4c083bd1b2ae52a2a53d7e99d25f2021047b31d02021b92b44530146c8fd061e9860aa014b4a4b2305c8554155d83b6f85aae2cf72fac61745e47e14c3fabdb5f238649490eb5e06948f1849add9d34e1bc1b78e823c5fe210681cd9edd53e704917802359c3449ce92228de5c524a085a387d9b99230708ba7262a81780aee87fa3fec83c8493c5c8140d6acadc711dc714756fc3a24822af190150b9e0c0b7745a581424917b149d70738df5985a0a8077d63cce57f0af5bb17c9713dcd6896dfedb1f90ac4150713e11f267044054ce0802085232095be675796013c70cf4f371b44ef44a3b2934fd2f76281be43ac75b8fa4a72d517567cbe12600f240af488a1854fb060629e8f1e868443ae64d45d00ca0f73ae04d2a403ff7d36a3dc665b7653a4a2aa9596471b9e223eee10ad6cb91fd8bc4b348826794d87d741e99c0a1936fc7d83fb64170d593be6d85309e4abd8220b1d17792c6b1534b89807d828970f73e52e359c264a505b208eaa74cb766b8f57773ccc40bff0ad03cdfa6e6ec7351eecdae4faa7a1e26b22cd1009d1b2290bb00136adc7c97cd298c54468ef3697772f3d1f9682dbeac66ac50e271bd9ab5b2d5f4c94a494fc8a89bc6fc6d8861667afb69a288adb1845461d350a13e1445f272d53009a25752f4d8396cbfc1d2b78ff124817e6ceec773ff3cf87bda8b3622f97290ee4cc0156447987306a22976c2d5a6c5a35ec9bfe9adb591199edee8f7267966a656d944978101379aa95688b03718d3c62869a1870e5702b8cc16e558448f514fb62ba7d0aa15376adb935d0aa01e5e69b6355dd594cea9e6eb412cd4da12d39055005c25a6af05014fb6ea14fe0185db575cec7e97f4e5907ea71c4db3346f26f85d3d8525502f6fc99e9f0d4631e26743e247ca5805cc1c60b5869fb1af4dced30e211384d18880cce04478f29c01ff810e41412237d218083d411d35589fe2c80a51f969fce6bc5bc1ebd08e0bd05e664fc30f47c73523d874c428436f592c2606a352378e23903a2801c3505b82eda4ca9cf641134935352c621dbe5fc11bca843049e47085da7dc75b87ad77d42d9b34c3e29793d30f0a40f9c164cc03d03b0a4d541d16501bd01027aa4dc83c2e2bc737807e047dcde5a43cd9084c76176d2b27454204f3d0db3fd5a725b0a17e2752b28402d89abea8253f5db48cd2fdab37f96ac708fc2fa57322aa6bc94937d9a047a0720f835ab83b182caaded57774584744f255a11171316d7d9c86e32963e388b3d3ae38caf96ccb60ece07297e82a6b551673eaf48b3766fc466a2468675a79024cf39047955392e69e2c8c60e1220fafa8016119426fed5f200e5f2ba2e187a94fc11ad14881634e9ea4efcf54b63bb83c03bd45c0611899824aaec3f5e1a0c1490de1a4e36da831102a2c9d9dbb4445e6cebca2ab9523fa59c9a7f01506320e444c8c9a94778974de21f8cc0c61be005d1f9362d0b2e35a38c45cb93256d190b6c88076c8fd859fd7b17aea57ef66bdb803e31663c5dac132712a066a10d206324e3c805d9d4923ae6c999960d3988c080f0603994a7445eedd22e87eaf72953c9f175be564ec33fbaa2837a24a4e27993269845b1fa9a5b69c3a1f566483b3f552da3fcb7ac8aa08fd70ecab7ce422e11de797e9854dfdbb06c815d4f8a0571ef788161a1db51d0dd207144e7e03e22873594f9b3ab13cb661153b65e024ef6ba9c442046891e9a23ee867458445689648436d3de56257fe2182b1669f2de2105458f98a1b949fd5aeca753735d82e24a549714552ee3a94d743074fbb850f2e615c91c8297d97a960bd87f420e3d3fb91cc74cb6c7d99415dd23a6ec8dda11b6843811272d190125256a48d7af44c8dd8746df4e392835efad5589401371f1bc31cb78ae055d90467ebac55c8ea11d2e314cfbc328c76d84e74c5a7df190295659884c854e1d565cf0f9febffeb114ce595a37b6a912634b76912130a26917807cc626ac64b390027bac3d64dd15359c4346bc38e7d01f04a11e9a0f17b4ae596800a58765e999be8707ff3999c488dbee019d2e59f4572e7bee8465d59119ca1e0621a6c6dcaecd6c1792a5bc926698e17984802ee7366682c704a4a4fd24a5d6237ec32822916f76acfebda2a14bdddfda6e48271d5747c08a1cfaafb133e6986de291bc79963aa5820e4fc7cd20cfaa8b7fbde8d00e557beb05984e7fd02bdddfb65dc986a9e79ce384e1968857cfe1f5e2a996f211b5ae5cbf2ab5f643b8d61df83259a6727df60089e97c2b83c8f3b03f016893b2a901675784fbe4972fe30a8aa79853f3a4f9b7c9a18eb8745fc20d61dcece8c9237394bcc74d68f7204e7aa857da95dbdffbd967ff69fa6b1aaf64ff880e049b0b680a646c66ae97600e67ef0c6e2f4c7a5733b953dad12422a1dd8b31001f7eb43a478fcae66d08b5bf0025b536ff4d4bc9c6315389cf669a850519b878c5634201e5aa1e7643e1944bda7895ce895b2ab3fb96f7836765eab0ca4087405a28f506f3f9017b8e3337bec484ed35eccdb81b9eaf5c5265f24b769649c0b2d4b035d905f3221e83d631d65d97aac26d3fead3f91b516f4beacd7a4c6da1c6e8b62ffcea8e00009b1e79aaae41a932b7c503655c7c7077120abad75b48913a4630255514fed150772bba4c56f39db88f3e2d09f777774142e99828cde70c013df10866bb9816d7c84726c9f339ae4ced85fb16c488895947977d6eb2f7c906cad333191d025519226954e56e505589451867cbbaa85165435771e39bee81a184ef9b6d3fc3d1fca61d48f9a0b80144b137a917ebbbd1e89b8286bb7e5cb316f20c905c8f3acdb4187d764b4a0888f02e29e06dd84305c8f539df0ae5e5889e2f8ad180346141acba7c6538b8aeb9cada9e37d07ab7d5c39161445fe3429366003da05eaf0a429dff2281b8bc76f07d61a2104c1effb27ba0baba7dc1d2ad572473524d5078de603e3822989ba2b9c2a7e01529f9c8374b2f57d4feba5e08ab0d103e78248e77a4d1a1da0323897eb46c0647e4362cbadf41cd2c191087ad1b2ec0728394fb6a847967607c02426940d7635b4771251c19cfd8849ce9b1ef1fc5944a16769bae098a348885091e937b9c4614f321a8a2ce96f82c3b064b5e2cd00c65e2e0f3c18c62aff14881a385ee324c6a643e4a3488eccce42f53de8294ff4bfaa284b52f4abfa5541fa7d322f882b13b487c727df4285a34122e3024e3f12d03ed98a6d78eb357c37b6f8b90d699d1d7c99c2f60b024177c622bcf7e52e80395512c7035c6269095bfbaa167b25b04ec8a58f1e41163610eb852f7879364c53f17fdf079fa4e484878de657f9a436ba98a66088613d62505b5f4e24dd1c637bf716184431ccfc8bac9878bb776c2a26a2b61bd293b7d12037e4e4d0b506058dfb1c641362c9e9d6d7af6beeeeee722af7f086bdb18ca47e687be8c88e2c08afba1b5f30b7b5b5e74328e535c1d9420570856f14865eb19009d833953cf3fa72bb32a18a410aac82923e113af99552c8290e1d062334c97ae6c9b369d590aa2aff9ef862a2869c4fa9bed4ab8e85abaed77c2f139a9a01f6511bd8fa3c6fd336740f3101c9041c811b78b9da4cc2edf0ef97725dac4ab209694b4166cd3f15899c7764fefa3f8f352efea0db7533c4f80f42b5a983d2a87ec4c6b572e403e5e49ef80f6367e875555ac88299185dfa06833c1b986f4b373c98ce24f94aeef9d02dee57e4c857d764f3234407063d77cf3704c91555bd3467947ebfd8392edfdf704c254deaf23ec3ced0638a6b3d5f0ca8e12e742f339f8023fa63f86a181b5e973a30f2b1a1b7b9bc6697a35fe362c5b2a9eeea83c039010020c7fb9263cce9342b096a7cbe009b5275682120a8d5a5bc2349c6cf0dd591cd8ee65de988ede2ff49f8e952892c0222d4f4aad808b6485bf5487490b63f70a1d6860ca56d586fda84853a3730277f2eec2c8b0ab5344467041c3e9b37ff9e5f702f282d4255d42c58ace9e7b363af37949a38f983b2089ada36627c70d0c66714ef49366005bf2933d579824bff5ea1f6d66860cf57352f11a7f3de230b3cdcad2306079fe8e633559f2fe1dc5a7557299a20a3d2e2e2fe417e60488c097896aeda9b5871264add4013ca2b7592091403911af159de208a2852aa2cf002c0cc7f0976f8635284974526b3875d3bc653b936c97808440e4e82e6a74165b5acc6a0611eefd8b2a4be57c42b085954cd89f78e54e4895add8552095e4c47d53f1934e42af810e8f92efb892b50fa466347d822589dd6f0ef7ee4081703aa44a6009aae1433de4a913877d8e85dc683b1bb431958892bbd94cb0e74d80026b99f3d07c181ec3585b64951615729abab499fa71dd9f1815b2ef70c39d97dcdf7c040c73c4907fc6963015388958b40cc72f03f40d50e97f0b75414da96187c95ce87fec291ddfb99c47466c43b5bef01a18f41c858a3351f4b6783e2c75c02d4e3b3e51215ed9aaff8e8a6c6e4214208d89cd14365b9c4fdec4a21ff2efd5fef0b00569f0a9ea2c51457878497423b7b5cfa616fd3a1a8bd19a5b2d4e0f1d946c0cc0fb2ada32ed55b557e1ff93150dbc17ad261ca8951e46ef49403496b1f973b1d582256d12faab3560d5139616e2f37737a105c95af36335603ffe836529ea4a1fed3c80538ea47e72f99e0577b6f1c290fcab7c34d3043902c468d012bc24515b4bf0511ed5075ff85f77e0d084eca7414468a8cd765e3c883286d041335b60a92ae9da567542a476e0a2944ccd2a2e46c0d718c8875818e6c129bf6b1664e7188bcc86113ad6dffd41739027615a3714cf3bd19341415f7d190150299ee69e6f99b5cf132287e7f39136ec0e322e4773e307b888e75f00bde3aae43f036ed393764a67afe08dd735d36c38dd64c5d41a88b564d754d511ca50588a9e48374e0b1667846a8b8ee7a325f8ad9ba690918a9aaf1f8e812a124be95173f0f39a561b1ec6816ad7a1932767755682c582d7774f2b90196cedafdeb22168a0f3349cec582964a256b0e5a10a601670bfcde1efeda2ca9ecff9ea9f73f2a5d646e09da1a89a8c54300b2f4f29a68348d456ff580cebcb67bca6b1b73b7d542b38140ffac24898dee39622158f6a2ddfa16195b2fb548c5fc9ebaca7a0c2d6f82f2a51d2f10cedf1cceb2a0aaf663c7ffa0995d2c4d96abdc2b6b99cd571c80ef3fa936efb9ba9ce7e7a92141f09a636f30bce77f80b4d0fd1829ed5008441a9eae4f3dac86abfee8fc858cbb6ea36ff6975e009e1c293e765e8983262ab577d684daac4796460f75a4910f3fb00bdf13f4355c8140a79a3e9ee26692a3bead794a74fad4f58abd57545d8049ba8f0ca3d8872b8259c284b2a50e514e6b3296284c4cacb9edac1cb78f848b20a6fb9835e8d58f8e7269174206a0f5c2ce40dd59d63583c2999f62aecb43fc4f96ac1b3f8fddbd48800e24c2da80ac1587bb95edb13f0bf8969ab9bc3f71af94371db2942bebc69ec15501f722d7277bc1a21842372c869372ec3fb9c1471fd35f3f1825f48e959487c8b35ad2468f6f9d8c93b5ec36431c4aa6ca6d3adf1901b0481e39652e5e3e87fe6d3f9a2bc3ae951e9b10757b49620238b1f153c2990041c6ed86bb86a6e38f2e4ac932165826a68df82c47941b22a6ac6a220e08cd6d1a0107b4df3c7f9740fb63f70c830b816a387dbdc34c96e0ca7a08528f96e3cfdf5f0362761f03ca484353a72ee0cb2716e3cd981981d4ebce393722b0ffd201ff31b54613114d6d29da944a85547e2d62170e5317df224dc10f56e67f89c804147819356b96876def0b7d7994dd22b89c75918c793cce88166c0f4234bad8d034742a12d1496c4a8167d24eb2f767d794ec9ee4c7d0e08c184b4ce2cdaa57888c04cb4445330bcd29a9bc738dfb99e37544cd6f235a978bc16073251098a7aaac9b780aab9f978ca4990d3ce0daddd294015969ff06f01fab4932cf01f90efc84c3c09646acf7095188970ddbb8f2aa0da4b3ab013a7a6c2e890a9ece69681aeb174ce7193eca298c83573ba0af12bd2f4f1a1efadba688084edbe002b896844da2534e7b956fe5a1b81d0d9b870878c73f99f17fe89ebb9f13b9443beeee2ab9ecf8916967a742f7b3e57a48c13fc7f5b84d2f1e5fc5fc1c69794f0059d1dbfd0c276fa7796a31826516bc3e34bbba73e076b154d6c6abe9e9d5d22bede344a3a84f43153a30b792487a9dcdfae850ab4e12a346b25750cf39908eecfa77a5b8da7b6d9e11a8d794ac0d0eb051de592d04268f47d3bffbcbeb6ba1651b5e647db474bf3cfb0942011089c3263e4e815ce3717f9769367fe6b8a453655d256d16d4cdd3deefbabc5afadf49d0fc17bd796b7c3a71bc14b4f146a03d6aa0e5f5ec04cdd1f851f9f0d4e05add2ad887a94e0f2fa0afacde3f46cabf2faeef6bf9e94952142c655348869339abba5d8e1ee7b4df7867656a3163ab31a0bf92462f3f656a61e60893ab64c8beb2f34bc6750cd209b0fcc5f4c08e8d5103d96b87ed111e6b2e3b71ad4ba3021e66cfedc41e53e5493ed23e6592c638c9b649ea7d1506d054d07b6d4660abfaa732017da05a8b1e9581714cdecf2b41ad19696ad97568d56ae22032a40a96aa074a2af119ace97745171cd820449b016fa4fdf557ca9e652365b747bb1158e3928fe2fb9fb4a633b42aae8b1097f10a78a0ecb7f1007714c543b1d95f4a449a373173396daf87dc3cc7a8e3df03415d882f4684a0b9013b761566252cb515083cce2a0c2f1b08d27a0e36ae2deb4a312493303f4f6b55cd0b778abb1eb801a152c26ef5f9d1c1bd2f83abeef5039408469116b40c7fdac1b78269d8d58b35bf0a7eea00c910114d62a83d108fd51b2fdff2f9099ffa0de99a9ecccee0ec6f984e89c9281cae7ce79a380be5a10bca2f7f638d458b58370763ec9b697af6f5edbad3a1ddebb6b67939f46a1a65aefa391c3bf696bcf9c23aff65e9c51cc694944c7e2ee1cfd1b597ec6e6808f93d649c70e8e1c0687e2e877366bcd580b846f812de34c016c00a9be91285e7f905833822fbd280003758d8973f4587352d0aed2066eaee9438a229e8bef4f7c50722596a8a26979f8aaa7b1b8705415387c65dc3977c229b3e89c9529880de4e2d507943d9d797cc4162dd489232c61f31bcca5171c38c57813cddeb98b9ce83d4de4fbbe9a24583c090fb979f5f9b0f203d3fbef3630f2a61a9e4174ba20645dd1aaa889e42b59aace667eb2f86588fbcef57a6d556ab0fc35b3fb09f5cedbd0a9bd69b7ca82d2a080ccaf04230ec317babfae4295472a786a2ce242dde0ed725a34e05e228bcab568b858fb4a4c1befe3d6004017b186335045e96dfcb2e5849579a4ce46912837deb84007711c9e823281f40ccd8482e3fac5e27336d590f543a052ab3ae36f57bdd9fda841527ff187d0b25af3c021d054513de3ba4b1064543d52be9ef584ce139b3fc2fd03d03310391ce1ff81990636b0153ba88ba670eab88fb84f30cd34c152d9fc12f94df90aded723de009033ae18b2a0ba1db78227857964a322a08f61da22a27b056247845aaaeefb9896d26ee9cbdf47e5aecc0ae9dcc04660bf4b54d9f685d9615fc1d9eeb887c00752cccc2f0811d43481b50442a3c1365e022bd9f8d2b9974576114d2c8b17d4432220226eb014501681708e61bbb1d532fb7729e17ad9624907b6332487e2993111ba3a1447f2af1baf1943ed3e450bc2479af9626519e80f6bbfb344a79c9fabd6a3fc47e1b614e02fa1338ea864a266ac01a57ce20a391e759b5c8942b55bf96f6e6daf4316d5aa8b91f42eb1a0a9961e6d38cf071adad7e4f65561843b114b5a45d0ca2cf45af950276a3219bc84d165ca71ed432cdf394772dd622fd993e770b8c687cf7a194e36fdba24b3aac8558f95163b2539619a7c757558441502766ed191ba468d152f3ef033613c5888ddc278b5b555fe87554426829a8f85decb7da45e7f7c451436c16ebc4aa0ceb7cdc216228a7e3134f335754a7caca814100555289d013290ddd98e804988437aa9023f05cccaf1960e872b2ce8b8378a46938f9c33e5d9fde5cdf1de50158693f28da7844128810ca86b2abca1a6adfbd05596753ef698bf6337ba499f538492a6ca233db30e63a4c9acccd2b30eca7f20c0d5ac94da2789e4bf6f677c898227800c10e9b38573d9e3b728abce818fc93accb33a414992d29492acac3c337fd9c84e6f8d38c0d332ee932ce53c95fa883ebc562424f3618b7f9341110a81159ef599ecdfda6de126c5a1637ba77d68a72ab114c4cbdd74f1b7ca5819748198ed63b3395aed54822c360dbed9cd337b8a5eb160d4c1c76a1bde853b673749fee1fb33cc0f8b7279c5c5b50ddb73ae366e355f3bf089df7ddcda95442b214f159b920cb99f2ffb210c1428fbc5db4a1a59763bb19d4c437be71f3decbf2281c581c0aeb6737c47093aa5418a4d34c6a428ea2d8e3b02dcb921329043744a99fdfb2c14387184942fa952ced6b194a80290882b7a38a832e1fa3da9d0e88ba9417faeef20e10572cbed42f13647e7952fec66d04d5d2592fa2e4b33463bb3b4d65c5dc53e56359efbd4ed6c54abc2275463e4ee9308637c587bfec9dc88f9601f5370a47f76c74e84fdb52fceb393ab01272c73d1bb1fad891233baf975744d3d149a674ed498640a48f9f9a8086c67d89afcebba9251348b2f89fc13d51eb45174b158ec86755e4cf57d29f1aaa0bf6f84982b332bd85cd46ea3ea29dad54249dc8c6f1f5e10607ed2085b2c762087117481bc580726ba56afae4f1ee25fc8cd7e0a796f0c591606f0ff5bb20f0097b4a89dedf0e03128ea898e2a54501684b2a34f9bfcb34325cfa4278e6e308cfab298fb2f19f2a1ec707868bfad2a55b26e4ad7ee2a47edd1aeeb63b0363cbb8387079a30885a48fc2061d59c59607bc83fae2b73a7ba33e45556642d2aab4bbc0cd03d4071a3997479286de59f6856a79862a4fd8459984fe6d0805cc20ca8663b4a172e514fdc996837795f9d1df5cbad1229c390b40f9f726f560db2382890115e4733f5e6ae715707049da19c17c70395e2d03b30b4691862cdeb37428bba5721d0bcb2ff62d775bd2fa60546458aeac3e13edd4f9982ab4eb5e642b2f6ba57ecf18f33eccf5f54be9caba6ce1e945267aae131941744af1f7411d5bc89910612c7480daf856fbf6bdee0c9584934fa22a36340d59b3447609df1db27ccb232f560ac6c1c8752266cea98e1800686f2e78909845c71795b502f9a4f201672aeb9f1c328d7e7d0cb7e79e6bf7d783ac58f0e962a9d19807671a4fafd204d810fc6512cd6621ca402a1d00ce827e3ea90871029ab8cfb17663eb288d3e7480d64f89b78111ccfbe6585bbb5fb38278d3fccafafa172bfecf20d1878fef5ee1d93c0e1c4145a9f13f4ec0b3e63a6859a268cdb5a579c3bcf65e7437bca95a4856dde28b9e6e7fbef8a2acd4b6041b276f1affd0d5d12304821dd708f19f0485df21a37db5856f99d9038b0d822ed4eb24640b4b541c124c75626c5ac8c0e86af038175770689fad744080e3c147bd3859eeca9d95f3e1b48db43b561d9f4db8c5871119068ccb39f1f7ab110b7482a89d39a7607bba3fe262516147c56eac629f367ba1dabf8fca35e77d5ed5423bd94de70c3cc2767978f0dbfd9ab71e8d8c46c4d3715fab015f40eb5c7110f09ce0807474958112ab9599a04c8e6ce7c0f8a1bb0fd73397099e5751eb25b86f274f36ad947dde9ed6f7ba02dfd9641cb950baa6cb837e8fec24201ff8690c5db7184ddc8fee60a0f0d9a29b28f2abe8d811a2b1e3dcedbfd6432629b286f00544ba083da9af7cb338bf127813f2d30eb7d97e4c34160d29cc151c9a753a8d5f11d47d74996c873f0828ac1c0009e83ae347f076648b13586bce705df62a8c7bfb0b4ba443f9315fa915d1cb038eeec4573023636bf01b6e3aedfada57da9ee40647f081345470bb9b9b26aa79a386e35dba439ac3de0b9e6627ce91e02f77091fe9b34f1d9926a5914c2a961c0cbbd2fc83dd392cf90f2f950daf10585b1f3430db0ca296d1f61d1e6a819d1a1cbb5438a1b76ad1e6a0eda93a9cbaf157d66a27a910f96da64801cb7f1fbd4ecce147616a730f81d2ade7250a83da7d294ae886a9b28e62f13ff16397251c85c323b9cc046513222507cf279b7db172ca26b9fcf90566d7d31997062051d9bce3ba4920f70b6f4f9b7bd3314e1d2696dff31c51883c4c750e00eae4b58047ce04e20d805a7a26282a302a325a4c435751a1992c27503d1aaea9d53aae826cdb7935c93a8d685863614ff6d49ad42df321550887c8574e7d48de1aabca32e56f170fd91be34f35683a13c6557faf9e3dc08544c1462a3e088e8aba084e8c35ba60b0ffec99194f68f4f25a102c1f6d23166f86318f734a3c34b3df0b5c29e20cecaf2b4453cd7469596115c8d7d499cfb3c0f97e8b0e92690f3cfad9a02a3aaefc590df69076ed6d8c0d9ccbaa5a1a53ea7e5efc3a567fb40db57b23bda632dcca04f8d43933d859b1a8d9456f0483c9d830051a98853fb29b1fac8d0736b7ad2b008324ca84c4955679d53a436a239cfffe6ad638a4fda27b797abd7621b7d539baab01c2de95dacf77133753e91c17dca8cd074d4e8e115c0c2460f1e81390fb0cdde338b54c894a5b387fad8e2eac96eb8a4737b7d53bbe17a74c790a2f2e4649428c3be227097f87808688b8ae8ead5506e7bb25f71053bf5017848a19ca7625ce8a342763a0d6cf0f7fb139439610905eb544ffb6ce93954d15fc7a675a00e462fc3ab2735f1f538b4a060258a59a994789e34add3308b3029131dc33f7246e78cac44d1c754b14dcfc5ba77d858d12ddb9b8dfeed2111c92dd9e569a430e00796b72496a51c2297b8a2e3a871ab9508f14038e92ea588183305037ccfd8900a78968fb021d7e5cd942d7423150dea1db33ceec2ee40616b11017eeade5c6beaef670e86faeb0e9a9acbb67b71f9ef24d2c18c5ffb1af43638733329128bb36c091a8e9b0e2af5a9fc30810b7ed1c95c006e14d6a3f43b87797a9d821f0c3c55aec78efa1edc274936ad5eec3a834f37cdde66480d9547069837f50c3386cdcbb1cefc778769d68e7f80e8b0962b1023443fb4ece4851e53e7190689a9280c03e04022c0867af26867bc17eec349319c6599f5ff0fd4361bd7b74dc24d5f2a0b4f5c94952b55203d3801cef6dac40fae72604ca60eb5a444266711844478d82809dfb896d4632042d5afd01fa1fc309545b392debba557d174a4d75b63b6e5d3f38a1a420f288f42807ef79cc38ad0b0aa8a631d15b1d7c40df8cc17bb19650ae8c3a05af4c59b80b56c8b570d41d98f607218cb8faaa87ac31b5139b46fa326979e36fee0206b1455846a67b0e6edb19a21a7c9a64e7ff0fbefa7dad0cc8195148749556ec680f3547d7f65a30f7ffe4f807d4261a295cb55a1bf9ad04523059133b06a5578f20a18de17ebfe9e2684781d7815c17326e11c5bd8e9cae49e8c374b836a66204bda110a55dbfbeb9c0f860896f559a7a888c86a5c4f3dd7c662e401387872570e875fa30ddf4b615ece187cf837507f35440e518c084be2049383ae8059d4fea83b4bee6e248ec0eb1505092a6aa5d3c4a9f7b823e2c517e5fef86c66f0fea76b21ea5eac6016a3e47561c78c9f91444c432d045990f2cddbeeadd6b6a42bed0fade305209d4dd37af9e7331ea7b12102b2e20f6597ac6712cdec84a5a5d4a659b5734e3006dba294fbbb836d6eac87b67c0075ea2c4c542ed9b698f29fd92ac47dcb0b22b570a09fd7311b859e0255d4a8bc3dfd1c44fc7f271e0cb3cbf685244637e18e1f6456dfa49e3acab02c202d3730996c115b4099900aeaa1b715bb2b329839e96f5509466a651897735bd6a315376107eafc99343da35381de5c2f13cb1c9e3a8aaecead4e271d96a24e7452c846fc7a416be228ac5b71f5397ed444965b3244b011041024b590f2cc7b061a1b763fb10f5597db90f4ffaa993692618ddcd3050ce859b66d6f462e37a90da7a5098ec891c955ea82a47742ab7d28b11bd467e6ef0d35c2040847a27db51ae1535ce0c59b237fc6418a53a203e07d1073bea271fe13bd872a5e6e467f80552706093f446f978789425292a22974053ec6bb2f98ab3ffec190c0069bf3d424c9ba57ad8c8a714e10c2ca59fb8e602cd29f457d5740cdf63533b229a40737fabf17156161e278951631705cbb7991a8cb52139f651e2cae02c9796a74c87be9ab5f387687c9e0d386269b1d85b9e4f439dca6a6dbdd19c51d5b3d7394503beebfaca28a8aca9bc2f15ea4fb777da304b27429dfd6b39a6d92da4eb987fccbfe81e9f69eeb53993d87847c79f8951c28c533b9a673a5522b5251e94b75dfcd019d0a555b25baeb1bae61d21a9540f3682773658e8bd9eeef4e66849a4b9c0534fa0d2ff03d7be7f6f988678c732d6bf8f6fec11655621c79841a2bde85f1f0e704ad941f9422bb54cae60b751506ef0400f3ba721bf11c69f8f5abd64aea11ad8e6a3b44786a1a840afc623aab826843b8284a73f3a804f4c6ac1f16d7b3370df4b1472c969b6b2e148a603bb0a0cb8c6c4daef80890454585cebb6ca6b07fa85567650d494e11f72b4838e247bb56aa4f915a635644861d8fb1a4612dc6f223b623789433f882c8181e96d4a873424b8d37af757904e43560d565b44a5b1875347ac3543636614ca4824dab9c49f01565c5df02b6ccc482c51918beb301384b281c8deb789671be7145d78628a21182a62fbc2b48b0e53f03600e86a0afbbe4b91d4da2c949b51752212b08a2069c5d8f155d9dd176b19b5b31df38a3639523b9de09ab7ca5abee1c2f8916923e5a5a64ca37980b8fcd4f3df64ddd937a606f19177cb7db06c89bf19429629d6967027cb54fba4a89aa1cdf428ac0b93719ec634610ce13a2827425d5385ba08fb653497e6eba3986f57f6580ef53168e432aabb25d7459b3fea3d0ade1cb6a73eaa7d4d022c2022b73537b99d3c8b306e00a32816d627b4182fdcc95fdd7ae4f36cbb20492b4c89eb09f849c4a6cfd8c6c62a9aa44fa7224eda67fff6504a73064eb9c99bcaa7f09cda77071c884b4c971bf754f4f8e7ec6b2a62d098913096d960f3ab997616a689761c94b41afaf3ff8760a2767b1c62b363038c6e78df1f7c017228b0b81b12a91badbf030a20a99c350d845360cc7a202f5b35dcec0abe7e04c050af469bdb224f2507dbf96430011509ed65f27506fb0bc06eba9a3fb1b1d585d5a6a0be6c160aca1270abb891e4b71b1e2302ac3e9c6b564c9e5e6917fbaf8452055119a9669f880649c1112f1a4fe6e085a0f277ab7289b766ff289090f97fe22414fed8024c20eea069e796ff1a3f28de946d6e03397b6c2dd574d6ca663b62c75728e9cfc5bb70c9599b13d5b2011bcb841904a7f3309066ad64531c1cbcd61ceaa09b753829a8b546e22748b685c3034d0c07b539851c769cfb90680564a2d944e2fd6c186075a6f7280e05e933fff00ae04da2a79ae04454560276ad6e2f15c6d3b77a98e10176e93b7f990d5df9bad35da5d3303e2689323dce6dd40782d0eaf2fa2ebf5927480730d721cd9a742bb5f71da880fb029039eadfb654331688afd929adca6f15549a69e68a3634a97e79bd5f269f54501f904476dc4d6af489415f018c29cf59af4618122e090c21eea39eac6fce9d4d1b1dd5bca876fcfab66298454bd65d10d41d48d222379ac810f745b66db501b4602b38622171e25713c6e845b99d9894680cf9193fd06c5204e9671499b74e417401bf1348fe219068039591559b44aece0f68dbc8c9ad1409fff9ace7311f4a999d2f7e93615a795fd5fa052de945d78e4e8009397d31a22e326300ebf59301c29f4957c0fc676689043eea55c550c8ed7b13977d2346cec22bc75c798a846d7867cb05c8da75ce1037733264aa0bed41a5b8c4d0fdbafc10c683d256130692d6e711ad739fb673dd9decbb7e2e3bee456bce8b11db5e8644c1c6b0c8c71dc628fe9b00910f217ca9b0a67117b4f27e899b5e256a0b40b122f6452f26d5bfa2bebc92e29dcd44172f50665bcd0e4ee86237582fef4a7ed729eb4a6d2bd38ea9a166b2c01c67ec572132b91e1ea8919c8537812e46905563bbb40109fd32d5eb3d74ca2eb289252e04f135c3d1477e008ec65ee3fbe0cb03e9f10838b5e507a72efef1775e4059affa3d3cd78bd94f16518e8b22684f581cb129268295b281103746348c288f0e904989ff638892ddca22952fde2cc8cee6dcc4b3601f22e7c27f1f7835bb5cf3112af224469f2013489ef5668870a0041da68d96e461ca3741505371e6cbe1b27fe4147fb98ec1c35fdf28db24d7189a8c1afa53dc13e5f147c5f6963a7fc7f55a785aa292b3af8570536fdb53dd1d29f77e2094a0350845a81b92685e6f09b4ca5c6aa36cfc54d15fe3086ae023b104f510c3c58202173a4b66052e8b1cc77de3253112998655b1ee6df9d81220c3d0e271529591fc04be55a8846ed23bd86d8dd6f391a629006e82f24947a80e2a8d172bb21f93298a1c12cdf6c87ea08bbc65278249e77e2014d5fe99addb9513b512394ddd49a5afac328348e072666a3c57dd8787587dd805fc5bb6c8d6f0d1e499b1453fe36e6f7716af9c074200f046ade96016dcc8502bcc924b8a98d9cb878e64691d9463a3d64d8564ea488cdf44770f03d261bc9a74b4f0b38e29a93b506d4b24893ad692c5514f9a1f50b77a315e8544847830cd520e1c919a2df5121d354a1463c582ed990b7512603d8870ef3520afc5cc79a93f2e77d089dc5e66c35081121254fe57d4f8eea74a7c1e161123163aaf1277690c77620ee672e493cbe09d6cc2e8e5c6781077085daa3ba4000171e6fe7428a16ee0775448a49c0fa2e412c7512ee99f3f9e74cecec15d4ff522cf9314472fd638f5ad7fcfc0dca463e08fe32107d3413a46d9bc398ffd3a2bc7a041b4f548f3b0777d0a31371d0eacf6e8026d513339db2d2ea4f8fb9dd326343fa5c522ee6842bafc6eba46ec970fb79833342a9b984d3864a8879036914ae5b3e95a3fea50b82ff75441634cce77bc80120706bf1c8e3386fc28e24e01d8fdadd82c89b8a9dd00d3730ee588d92017965a007cd828529e39ad9b4dc4ef7c0190de638c43652f793a254a540a205d3ceff6549ef7514052ef8183d3be44dd915b4e93d043b8eef572273e8057ebe4403f5d0a2c0089d6a4aa87e93f8333d1ac8f53585f6f7709e4717fea801ba8c9a8d74840cc9b500ae4d85318f56885fb5be4ca8e630abcb0a82b3988699e8059f139a48304d7dd4b006d60def002a6b92b6d7edc0fa30b3cb1d2ef68a7be5e294b49172e7fd1f8851825140a29a2f364eddfd776a9e288ffa50d34477efef9f614cf6d2471d52da1c4b538e4b7986752971fbeada2194bfdceb60d68e4fd63a5b44733a4f559009a80dcacbd4c98cf07acf4d16b8c76ccd9ab774af1e4c76782b7ff9c4bb856f1208dcedc0ab16b210bb46f69bb79ba3320485dbf5f878922b797c339a932cfbdc9f717cdb4c9c5d3afa0091e107bc46204887239483e11075c23f4f1872da5208e34ce6035c68d3b28af48550819b602e271ae09e99f794972797d94908deff0a33a925138491f7cd3debc50f38bef2dc0e4ffc14c2e8e0512de35e02e2073c85d08a1cd57d24e748c76ea49610d243502e42abeda75e138709969921618030025c3a0c4aa93434b2dcdcaeb6554e48af63d1e4074c2203061f934b31060c4391dc726e6f8d820164eb7b38939bd233f3b925236d1b95de8839329a8c4b1be02a4f78bf940ad6441d4caba6662ad69790ad3c4d4a8d9a8ab3cfbc1e07cf9f700a7e3a174c1a036f2b88de6db60904174679a9b046754507144826a05b8f9c50b0a55088c9987d6803925d67d447fc3bcfc97f1fb0ce6260792774e8b99d8783b1e47448217fad9f002a0b74ceeef3a5a552f0b2e5a869c5a478000fa3703449325b38d1620a21892a3fd97e216c0467b5519b6f04a543dd2bed34fd1708ad21bd0418e2c3a500ed14997b421f65ad71d419a3836e3cea9f56dc38e6902491e20be12c57e0ad8ed75214a8c4f33e4f0b846774f82b8c4b12394ce71fdbb303ef720cd8070885a788753e6bfb7d10a71f3a4f25676f6eb81bd11a6803ded2bd0261c889b463b2c51da96c581c06fab9c42799f79be5747c18441ea099906d0ebcf7262cde2c9e6716f44463980c563e27363dc97016a3e5d1afa84b188f82baf0ede3c9881e1ff6ec99c91f8cdae90d9ee4d1d8f2d918616f4900feae018df5298eab287a5391724f4556b00171d27fd438aae95fc8400b795417dd2d2ad6f29477095d64bd78d6a2100a1a6f9120f4de9bd70af575957cd6cd1aa2639f7bf1b38174e39eae2d56c1cc08ee59a499cac9b5ffabe406ee007db1778f0bfd56d7ef3df8875561975066898e1eb188f8731dd629234aaee7ba01ea8d8c7ba4212a02088d0bac266b9a6a816de143e222f724da6a78ce38900e6114c786fef26965e1b7ad68249847778aef0e7d9ec28ac0593e85bea7de7557e4abf998a86aad4e1231a20facd6939b9dc8a0573e457850a07c5f7a0cfb20e46297fe0afdd9510789f0752a9e2431313307100ae5694c0d04eca28aa7688b38019c321e33208cf015a57b807665149c3a89c7a02e388d7b98db6dc72071cc5d58910c2eb166fd5929759f948ff895c266b8be469ba81d2268f63a38a21e0fab9c4b4493cb592279c1b99da3a4432414c6d3b0d2cf1104bfca0a0bd1baf8874efadd61544524fef80a2f7808f7acd844ff4141eab0ffc13edf5c3327b20bfb265dea95896a31654fd4b700494384976e1e3b5d109145e40aec9ec5152e6505f6f541f01949b08d71640fc46a7d6b1f0d74b8874d963ce21ee181a3a7426c8b49d1927ce21bda8937830ac81333bc8e00b0e72b8bcc1217f25efc8f6bf5ca420d63a3df341d6579a4149b2d59fede8329ad32efea575980cad10384cb809fa459c0946ebf299c84dd19a69925915a3c242206e638e8c17a2a78587b5b585e97e207ceed42f261867b362f96bf0c74443b394ff4afa93c3ed179b065128b54f3e002bb88d36ab30fae5309c532c3d5b987cc1e85571cf2cf53da6d339d984688394e07c6ed7958792a4fa11bd4927c5ac98f4002572660db6c3c754d22924c84949fa02227e53cc70aa25e23649f777f9dbeed9fe05fec83230d439f0424e187f78d2ce9df73171f4d859b806fe1079851d946e0cb8390c7bb02a5adf94c9ec36b495c1184ceaeb066f03e3fe186b77a5043dbf028699a59fdb385383ff0b9b85f643ea53eec870ade3d3fec3e6d42a2ab7964fc085fe94bb5213eb0647877313298bb784a0992cb0a1e9b8660efb5906c81b7d7cdd80451278d1b56592132ae92d1400ba5679486209b923163a0bc2e7b473b2cfaa3b6d4f61676d365aa1bb959653b49844a0ad6d746660b25251b2bcd46d1fbb4690d247677f2d613f31fd1bf808f79464a432edf1fecc33bd201a3ea4eb0fee2745b3f752fd6337941edc7dace69610d2347d26c28e78400669f2a79745b09e3c4bf54aad93bd186a30b87bf8fe68b6106efc9f5a701b3b66696103f1526f7c58b8213e6da00319f0af0f0295797df420a39b3593d56bdcff31da9d1bc25f411163d3c97e6bf482c455be33b8c293a2ccf8fe004192144f57a705113e61ec62f6828afbd9a11891aea8d94e7904e4a31f5f9a85d236e790de17d2183788854306edf7f9e3703b9464a411c0f19d6d709d301a3af94637d4a549eb5c355e5857badebef057b668413aa6963851586def48bea518d0849284e40e98f2ef058e79ea34799cde554eb8c5a20b0f4b0124f4f60f52ba76093cd4574e023493e924585e48f0c401af1a6c8ea932ad53800c4f30d9d98c76b5523805247903c7950826762d0af5585e775447c08d764f0f0a0f9707d716c5c4e9b6d86dcee92827cbd407697ae201355a988330eae6078be99b9baf99ac7ea863cef4f9720ca497b2d8b12f7d79e23be46791a13c04e66a0afc9281ad7c9827d2fd329b281682932f2e5dc5f6cbe382100a5895c4a1951ebf6537bb1e62f26d4ae439f0f2b6c776e674db6971af3f2aa976d4a1cb09b78c91308d80557f6b07a8258962e7d7908098682d7b0e780d6d26df61b20fcdc8e4e1668b1b2a54cc1660eb1674f96a05cf982b544cc00b44a812efbe519d1a891f2c5b431766aa7b45cb28381b95704c0e068116d03c77285d00c0405638964d0444b9e64cb03d0d43944f5200fba9fc651ee54275a87a423234f41300073433a1cacb9d511ccd3bc910fcebbafa711bf211578a5ef65fb82eb807fd807ce8f7dbed006e04fb77eddbb3dbdce8dc357e4950a1d3dc01c4009aedb6066c88e1558e70405eb1b197466d538449e8afe892f4fda8cf3193768400568bf5f40433403c70b6625b1acdf564b8c0e9839aa2a37af5f3c24482c6bf49be12566a807d2dc512bce1571b9329e13140cfe708dedb24ae770d2a689a4571d62570f8593b4e9d60e57fa1c3f52df4d56fec1729138469a5c9ee5af9c23f7ace81bd314d85b8cb4a20f50fbe4576ca9890c45aeb21791a70ac81eecc01cd55ad35eb894e8ccefa9d9e8f932683891bf2a23859ea45c1f68299ea10fac56976c191d16e599d0542eeceefe17aaff2e1c1857492a5e19361985c5c1e9d46a08f4c6decbca0c18fb429dc38053021bb597395f327eb50b9b05f31dbcca5f8506349ff0363f2b4c2554116857bde1b1a53c799d4b81ac7f7d3c91689209ffa83595ed3d0615b697c652ca53bbb230687800154811b95fa3b70e5eb25a8fb9442385857d56ea77645776284d245d6a8ebda1ae5318998b0c5add75c1a0ed0351afda46dcc5cb16d8fdcbf484eb7613f63a6d0b3ab4969392ad2ed8d4354d0512ec4da911e2b2ac6b787d26695bf95fd0ce8e9653917565ffe3c8ca3b76b93927d5633a46a90ba4e97ff1154fe596905a1c3e7602e3439025cc2f9bfb1ed530b8c28092a0a9ced2c898fc8f504cb52c33d7e634680c3049e31a7e98a53d3bdc38787acf2ca54f8e2cc36d92d1d59e35901839fcf8e59e3e08f022fa3750bad40720ecb2a315dae1c7eb6636ed9924b70796ffc3a5c93a946c31a663a2918073f92ed4aba6b299b36b1661637a075f322b64b9abdd04150ba6a6892a28fbb21ba14b966bf9b6e0b45307ebf5fef20e78c0753b57cceeca4f219f87db888a180bf36b36f00d78ea3d6111390cdf2d2543efec9fb7c352cfad12f38d1674d568b89abd4d58a0384c653dac0d56bdeaf4a9dcfdf6753dbda01e71d8552feedccff603c9004c9adda7b5d7ec956b6e03f4edc24939c526c72c32df5d2c641d07d447c2e7953d11f355411ce455d0051651139ffde18b51e60f81f61571aec2fd14418f3d3a74066ead2f693138ccdb461cc971df184fa113637657dbebfd2918a007cee8f34ef10f7c89cef0ceefd8c7df4cdddcb9cfa459f24958eabdd8547cabfde409ab84ba61638197af0550ef24c68f35c448c16dd336823205cc79595a02b347b502a343110100a31f3bb9ffeb2ad6bc49b30d7ce09fe376976368519e2a71d7c5bd002c0f34a1cbd3b01a35a5320b603838f81a1e6d00e2baabdcfc7d4cccbebffdc090b147bf5171e89d92ca6475f3818e5259419d8e22fc59a498ea6d6631bac2ac8ce28cbc7f0454693359d8a5425bc160160fd1c8928883b37764005269b6b9aab7e9698aa7939a2d3d9f2f88f5b3a61cf603603e7a3c28be36aa7f7312c8d0452e81486fcd24208ae8f6a44701267cf4365942b380d4a59f030a0263d3ada696d6d977a105f8d70fc5803995e12ab16b2505e7bf0fed2f2f8a413eb8405a638d7df3e7a549bef5a7e8f56e3b3892a9f1ae91efefe1a1cd3457f9464fef732708f5084e52dc821696929f29e513cb567c5369a2a9443634a3951f045af614c29771bd2527c82c5c386e46368b4bdd79d367aff78b79ec7c46bd00c749ca2f9835ad8c66b8f4cca8a87189773b61b11cda9bba8158b83a2a655fbd2e67f9efa9a38c516158e3ab2d8c3ba1e3ecf172015a16ae4a839aad9dcfca7a64e2281a222f2666d78b0d274677e34f84c8f8643d6610e16bab3b3ec700ce7c27cbb29cc9c455a69a93b27f1861e82423f79443d7f933546754ecc0cd937d93cba14c515300eef2e209b7dc275a9341296500eb67382c692d9286f9170c8902c946764fa55f1b806d958dd9e1aa007e829dadde457b6676a6bdf1b982faca5853aa5177238824a5b2a0a0417cb9d36dfa112a1610e885a1515199e06a84e26313cad9463d032dcf59f38920161a6cbd2885e87c6a435e3cc893324501f1d9e74bc7988ccb5a16e5796c4534b1fca7c8c1f1a35175372d8397ee3374f843948aa983f60a2d6450a9008a0d4e6aed403326180e893e6756eba22181ba656997bacc91aedf1a75c041ce828aee6de2eab3d7d68f62dbe00fca65b09f02dbfebe5dc2bc1cc931b181b7e444427430a793ce3ce242216216142b4f83c2f94464dbb37084f191d5a392bf9e96ecae5a4e6bca2467ea6ca35a28ffdb03b04c40443bb2a9fdfec1771cac1c105c5846e8de62b425e638f1cca1891d76940b9551fa5f75c0e87cc6cd2f0d204f75aaf4f78bd3e3a2daf0095b7f437491fecce220fbec4eaea3d6fe242a498ac586dfc57a17f1a9f7db18b1a8bd6b53aaf8c607d8638db7f33b28ccbd9bc1cf61a7f9de5ce7ebb5ad13177f72e755fdd981e2d1db0cdbe606f89c27eaeaa265341b068bd454154c0d089a29b2c18e1e4fa2835ab8ab1139e9874cd88fd6e8565ab4271e73d80da8b8767633ac898e1b1c09d57ca97f1d2fd234c09e6904506ebcc1b53f5b4e26f7526db70a9ffbfe0c0d9879b934d4fb4cf348fa23bae4e8f3803ad387d99c349fd2353f8eee6575b9a30d12f0188b236763528594391bdbcdf386f73caf1005976430201bc95c14681c6ca51606d077ed601d0c3e8069d288adda9666eb72ab3cf4fbbe94a42c14eca394c287974cb37f4ddadfb9144e06c02ff3297549bdf6900c5d96d55a34c22fc1a32e33c7750e773bab6fa5ddca28ad96a292ef4bd0713390ac0a02355473ff5cd4e5dd3de491869a3fbde05f246f8ae1e3d43edee4e8dbbf2d18227f3c662ed89454241573f4a164892d1a04e21f0ca5e68def6f77fabb974cf6521efca4aecb1b92e61d584f2487716d155444a42656aa76fa9613b73e01208cb9ea20ee5eaf5e85fd12de1bbf860a9dc5b8dca4aef6cad7a9344e9bf2c2aab352467e9ea08098775a4513bf6ee21afd7e3730bc1f575909c4ba5e22cb37192ce5802828808e915e903fe5322a1a3539423dcc0c73fb91f56732308685f942c534eb94a58003097ed6dfbe1405a784fdf4e548624588c728a22d690b8f8fa488655e291a88f1a026e41b8a2c8bca8564f2be88b7e811e6ec9f0df54020687713946081c5c520666b8b9660a103dd575266181027e3e1b4785f6f86d9337fc35169134f96f2727b0927138ce59c4746890e653d9f3f41b72b565f26bc9be813ab0b063b28aa7a97f0017393366d2c1f66fc4a3500ebdca9811981b1c8754290f8400fd1cb50553cef3aeb96ef7c53fb2c00ab326a0e9c839c5066f3d4045b76636238f532e08d1a03872efde8fd3b6e391ff7c8fe534e79d18995c6736796305c31e64c0631b8b9d351559c4564243d3f182f85f78b104c31ea910ae0751aca24d6507a2c7d1337397e115b847d31e6cab5125817a3f2aaa1dbdd7e0ddec7b26e08bc6d97da8cddb876bd01cbc12b1f75aebe9022d6961a5c8182678107752c3a7a4ed3ec3a3ba0d31b529a125c305795dc861abd55475cc869d60c275da2358edae60d0a3c7b34b725fb5268a5f2bef20a35fa45879aa631998e7930e5df8eea775f5e68385061e01119fab7261cb1f46446870f163585f20266f45328bf750cc50715d615789474d67b4724dac19d665937eb567e6235e1c9130b3a86ec958c6a58ee679258c3bd828b506d026df9c5c02f8c95a73f8b9813a69329c9ef494f1d947528f26a344b072d2eea9d8b6359adbf1c9bdc017685b04d063193a3f53413944026e0bd99a2d8c43c48afc0da026777596fa47c0ff708dc8f1f8d3df291d1b4478038250668cd72f8a2e79c58d17182aa7243e5adcc8947e8a62304d4e25cb3d00e211045bf9d9da786ff9853a9d5235adc9b1daf2539c3365f982d5866ea0cbb309aa2822735767259166f84fae5b7d8c96ff54787f428e1a0793376687f6815ce16824589c1d6437a3c0f86deb2b8e737cdfab8b6a06939eb7928d359a18d7e76ea99467462135183a24a003e4bc9e4dee7cd8384f13575a608d81cd7ac25de0f2722b81e0c984f084c0b377210558f6e3040e3ddc28080055a5bc4d99c0e6f17347f78481e67a58634cc9947e19e6006527aa04cc6f04b38f30b7cf68555b4c7022b6df07bfdcaf2667aa8b8eac8e85d5bc0d8057a7534548941617648cd2390c945933998c1e65be859330268f98d7105227639bef14b67d66308593d8382587e5669efcecdf6d61c879394608e7d3f1721ae3ce5b72359201ff98a026b7e497e1a051132fb965133264db5ff22602899bcb60ea6af77b3ac0e7791d2101f046772a02dab2deee40eec3c15945f7082fed096a6fae1d85897a81644369cd9fc6c072c810fc1d65726a28cc08e8220c68e65a8cde171b7de79fee3f7d6d786d945ae3658139b3222cd0f0600aaf1b18c6d22ed9ea82adb76a54b8a5d3a9b4f04dbf89858fb3b6f68314335e2250244806432acfe715f654b11bee69dc073e99fba011fe0c8f7d9fc23197f57f01c8cd9a557aec3a557d3e4d72350d440d807d7c885e206f1924bca12fcccef6560c33e6b9332ac3e70609436e3fa147b3de2b95979941d55f8a0d8e71545b4fd48d3a40ce01f7f5d6df20c6a94ed7e43ada761c4ec257b8e0d9d4b232917bc0c68627b6daca8ff410b04f743b51c89bed0fdc160a58ae1f760a9247836ab48d45211f7c77471e4442ca0795b882ccb33bbc4bf350ab7cb97e6cb65ce76e7c7bf26d6826f109413957e2fadb10dcdde1d53e9695730822d72be4c9c3c3fb863d60cbcb3f2ce9403f3a8022230ce26a83b00e8f58d061ec0e9b73176c732455faa74fee7aab0cbd068bacd94023d8fe2052e8e662c4c8f9a619350ccbee0947d02e0fc93324adafce4fa7a7885e8a7fd1777719716fbf619670409e854d4e54f8d446f8d0eb682ef6bd5ba3ba68905f50a53a2b55f03bb11b38039aaf1484a0ecedeea63fb14630876493ed99ddbf00901271870a485818066478b3f74eb4c30d051706d01ada2f88d55f5d425c32f2e5c358bc65e944c183df2e196bf48391247c0d68ef8478bce81b92f9146a664eabfafab6f313a79abf13201f1b1857299f3ae6a3fc20db9da9672cf445cdd844378532419b61fab028d354ee6e3090ad0b050a0878bffecc61b2336550cd78a7b3ea7e02ebda811f9e5e7993f268a5c224deed89ce042a88e586b5e4d45bf4c835d32508551007e6277e01d516d152b1c1571d698f8618ef505d5cbe541d51c936e1810a02c64afbab9102851d884734c9fd9669f62f3168d2b197b7a20f9d017d46d7fd57eae7de4314b588ea0f896271619e88e68098cd56589758caa311d3f01316b09ed03afac4e05ed52edd1f820b815c551a259f7102b83b1b3df50a13927385642a42e8fb55cb090b702880ad4a005ae6c4102a418f26013555554ac1e93c53b6b8eb990f7a99ad204bb5f67217bd6db8811f687d2de05e45eb7222f7e72387cc70bcf3332f12076bd42baf91d368398d82d5d728b31df659114a31a34938c4597e4c6b7bb34ddf8bffa1f1ce5ffd84239f28d0d0e81d59d0b63bbced7dcd976d790b1830befd0101998e960a9dbadab27aedab5e1ca38062dc3b5e25e7c9ada1611b65891be20735bd7a9ae7b43629dc8ebcd24492a53b74bdd82e314848cd5fb43b3a5ae89bdbfbd92cf67c072904c227328065555d98ea263a90e798f6e6618dc7bf11b09727f2a76e234181a7722911951a45dc4df4bf52149fcac97fdc0d1d9b55b310b9e6d44e3216f7eac5ae46a998c2f8947a2c63a22c4aacde07754321886857534fdd54b3690ac722321bc52b63f605428759c490f5dcd7642d0ff545b99bf6c5fb6757afd71afac31345bb0a2f7b6449c19c0076643b1fa4d715e84844655b763d32d5e671e2ef9bc3855783b7c1663bbb423e18e61b1edcbd29a9b2e10856c7dfde007ecb064165a1a119eee3223db6ead9587e096a8a3b5388ae64b143f3ca13054985026b0d3c0fcae38d09a8b23c5cdd8d179a7960f278c31dd269cc6a88c331ecf7e8d353d6031bf83098be6020cc85b08914f78b392e5e589edefb0793dfadad19116b813f3fbb12ea78da7d246ee34cdc05e4e49a9a883203711c2cce8911dc1020cd92c65b4bcebcc408c58fe1e404839d1675f89ecfd58e5b2c589af6b4d7e0041d33135e8cafa9e2c27d4263f1b61b01ce417de38907660b6a0c7c98e02e53b23f9884d7887386e6675b41f2527393ac271d333eaebb7d838be7f9d4affa8abbc3e3cc51ed8db7f6fb53bcccb3a956849126776930ec1c7e79334748b11139659a414c72de2048a094dde5f88a7066f72c911f8a23cd8e3c7b536d62840071f145651fecac63ded50b5ea0c730125a2d9e8693d5d5bae2315b72b16ab0ebb09fdc67fd191e01a4d098e5f01f6523df3474733a73fe9e1dca803bc639ef7854ab12db2fb66b8df1e4653f518b1a07f88e387378389d8bfe87e9890441eb286ba2e31f07e57b35a4de9e8f25742480f60b2232084dd5b90780fff6a1b6ffc9f9443d13ed3c1947aff64afcb4ad8cda6ee5ea2fe141dbd1ceced1a53d333eb92fddbbc1f63610d95a306030b844b1fde4bc951e7b52978e48d948a5493453158d1bab1991ed18a9d6af47b45113d2f8287fd3ea4c9be9895cee6dde9643e7eca034c56f91d839392eb04b73c7a70970d1865facadc14930ccc53f395cd6ff41d5c4ae5990df8184f9bd66e6f7160cb5a2eab192702af1bcae28c8075386f6575b1f2c7c1e994318e2103707a5894cbce788fa415d8c28c014ae15343c0cb9dda0f8086f9a96744665a74b4c37831ca96686ecb82c660ed5e884da5e78f38a2101c5c9ba9d6e7f043c776acbc604b0435448dce420fe9cb7c1b05816144c8deec6ca950d5c36574cd863892498f642217be646eb41049713c55c75e2597e6f147d6807542a0405c38a5a2b34912d898650a24df80ad326fe28926a7952ff2a0d19737690b22ea6ba6aa55e2540f85539b65b7614fdb714563760baee04f0bf0a096c5ee315798bd24143832159bddb23f227720284b5300bf90e6917ed4a938a4a877e8aea479dd5dd87a804a8f854a7291bc550c0c9f990fa5edc05d6a3a729663ff312ae78725ece9fb579cee689db616fd6bd6d563e5dca1e78230e9553ad169c4476cdb574f16f480f8b153aef04729c1c9a86cd6211efc28973bbd94be45f6a2260cc5732059f8ed81dcc94fa6aec5efd29d3b92b22933d06c77187a359f8290f31785bf5c3aca3bc962b6d593a04051512847cfd10d2d348e70d9307526b24530d518ce67a0060e86be328f5b966ae48542af9e9b8be190e0613391549372c0238de6552985e239aea182ed5d4ff2fe541d8d8b985054c5e0ed85168a2685f66080f5a37f3eccdceda2f8c4b232741bda97797699d57bdb8bf9e45a7586b5321a96653bf212f427e77622db5c9885349e42445147a4d2595363f5abb39dcd212f1ee0bca504e6b4afd484f4d6d3cf98cce9f20aebccfcfa3cf6d0088b2c7761757af30bdf5d0759f1c9a7c1bcb54cbdfb8eecfba53139b6afcad6114e8dc489cb80cb5edb97a6a4d9004eb5753465a323aaef543f49e8397e99d28d02e773c78dbd5d511a978bc8aad6fb60ce934577ff4d81b3dd68d63495434fd04441dd5ebe02c01d01e2ce2431be2962dc55f87e9007d4f86916c1efb9237cd51ba2914bef840fa2870d46ab29ff31108d010f0fa3683632352b85a32b397a91a15eb063e4998238923d88668474bc3e4a9988fe09c8a8d075dc75951937efd46112446f5ab4bb6b211ddab7e041d4074dc6f058b9c76c9ce735f50ba33ed6545ee9d3c256ee8ed9493e504f30c4f10a6bdb54097724617f67695359cce33a4590058d4df1122f5fa4041bd8b1f3547912d2249b1b2098d27ff8d405ba35dcda31f6085fe8e2da1eb9c4289d3d53e3a7d77968205bb7bdde2dccfaf683e600f86ca6e33f9714688621619b2c8e28ba35108e819676dc561c8e90b257f1682ee93dcec76813f544920ca97ac1b492d4af19896ac9c6188424fefa36c57b8370f064e81e427a90ebfc76d30edb138628e8138005054d620c1a785db05094089220f968985dd9ca01be253069dd69da2c1e5d5e31e5a0f41945a70d6585ab079b872c4f47ed7c9323991f3558f9aa2ce89648472e3efc9dae7fc98a79cd88b55890f9f5a685e222c2efc6289491f552a855d547783a2caf99e621e50c6594e6667462e18f5a04d1a0245cbc37ba67c2f6fba42b89f30298f24c895e15c0981404c43d2e24d3c0c617a071e47be48a9270190cbfac41fa227407e00f225378baa10755fbbeb3346431612b7e64cd4459f9e1c27b79539a94bd42c825813f8406083293b305211f63b03293f3643ad307d9fe2794e84100f021efd1c6594303826c5b17e8166a5ab8374e24836213a7657969dc406e95c99e7220dee71991091a04f74787a627f8a99b8ff001fa473c1aece43dff889e82800e7cbe59e251b7330bb4823d22fee84fc04ab40a61a82b89b33d4c96e1364f8fcab1f4559dbca0fffe13ec78e36a4f0ab70c72ed06d6b724b02b991fc930a6c83b8ae1c5d4202f5643508aa6f3ee13de9b00af807b67d91397ba89839913b53291ba41023aa7b756ad76551dc09f59c9f6474fe36b8e8a69ca93c14e560b16df6454689c096e8a598bfd025c9581e730f7f3a5331cd6a5562cf4a6b0ec289ac3b9e6dccddb32a6cd33ef278345c02d22eaae9b2a065db7503eb08598e59d5b9411a06700b546a47fcd974ef39941ed2c4589989f34c48c9424157fc10dee1eb2b491d756613e2769c689a37d79490e20fa8df63edc92ae005615f73bd0ef1de7101720787819c717c2648d925be719af6daab7a57481ed55dce5f0f0fb128d84b02a254b148cb1faf31cd85ad638bd8337d31a80a234e3e3704298b601e473e74efe90536239a8a732ea5a5c9d6889892ccba5efaa23b24f300c2bd50174113603b2fe5d4495df0e70c66233784187e50716278272c71bdb5d3a0e93fb28b5ab3cd41f4d6d53b5bdc48a7ac53ca75bcd747c468c0618c709e929c7a4dea3e57012ed560edaf4ba7308091ad19d8761f7953e7943d253ae066ed0eaafae0aeb0437ea6e8e1c8763a7252924f6ed4ccf62005b85b571d6f2075abe22c12fb383d53cfc401a7bc589b93222b2604df0a45854cdcc73a43b7f192d6cd86eac70811606850a0a5ffd0968cfa8fea3eaf36f21fd193779f0cea6ccc60e5d4b1f489aaba1195d76688ebcb7b1f202f712e540ade44367fe5eea55bce6ebe2fe0a3567b64f8363035202818e10e5cdf7b5a0e016d7b78a88206fff5a494b57cbd719e60159db2b30a8c807b38a4acb925aed191e35d1e9da77b18de98004549120b147f3c7b445d39946629b470070d98ee8c6e59f8283de79a1f517f4d0df3f65ca9921c0ca5f882ebd8bb8250e104a1fd656096b706e6b634c88d3ef8a55befbacec0f94b21c392afea47b67a861afa0656d48a9c44a2867d2972fb2231ce6aeb585d69e4ae3e5c587a42e22c2b0637eda545e02203b748d1db8b1de0071de9f480d1cf7bc91a56b00a7719de419452a202d141738394c05e721a7a107f543b344a81a422a96605dd800ae458ac2097a170d83cf90121c280da0e20a20a09170824856653eeb3613224bf3a2abf7e595d02b767b112fd407a1ad901632a129215633d9b6413779d08d91646ba7234a3c1a1c8645a538b4ec9d75e3d21b50643d23bbf14beec96f8c06d8f46489478d36fd435cf3d7327ee6db85b7b01f75e5dcdee69173b4db2c7a3b7e0e88f5e01f68300c636f2843cccd7a7bdd93af9df34c2992a818414d4cffcfa5bff1997f7befc6990e4f21a707c96c33f66899143e32c08e71f107fee5a2f199224617ddea2df9eaa7c564ff99ac2786e854081a276d08a841f73edc1b95ac36d2d281747f7d20b1dd1ee3256e6297de8262b0e8bd2fc79b5fa9e1776f7b919465408fb7e283770b8b377c41ec91e55fd0b84a0e42479e1d2f9c48ec1e346325a2d58efe316b19146253acbcb2c6afa6822dfa9b3c8e38f1b09b16eeac00a5a570457aad56817a0f44278568157cad9ac02c74ba4a03000824f53b285ba05daa63412f1553be98ea1ef88cfae2c0ef9ee34c78f8d12f2ffcd048981f6f3dab14345fa24c2a26a49218a5ce7bb4b5dea5d0b1bba704aa4c7d9eae0286a568792d7f7c870eebdb75b15d15903840a248670df3e015cf73cdbef6cac5f0d93db8af9d98a4e27c74cc0f4ae3008124973b871facb2c212076f65d2ef09e22349e4a2629882745f9eae685ba8ac0ac31298a465b2e57b9a852e268b7b3c978979b0766fccfa939bb5743a19c76100d91380aaeab23a1442415c942f900ddc7b3bc28f65489454ad794884e90e8501efbcdaea7176d06132a1066c700de93da6d40d87856fe1c46a9e7b4c885c64ca40327cac73cde8477e925a4d381febc57f46da8b05ba90020ada28489341460a497fe4fdec3fd2e56fef05a779118f5f36a826b196d63b8009198f352bb9707816f58706329d3ccacfdca87268e97e6b71aad8e945cf361614aa3c1dfd78dd79d8fd8aa1fad027eb45074044671f4726a70e802f874fdeb72b3c7d2989d963d7c56070d9d043bf2c491240fdda87ae6b2c2527b92e7beb321d7d8916dfb121cd07577b98b457e1f6a816faf4b135f362f8bc6212071514c8c36d0e4cb8c48f8730b1aea542c47576fbf184973a37f9c31e17732ecc28ee6099793e91642036734fcc3c94380cdbfd78378220c65a4e8019ca428b794800cdba26e3733f56cdeea7f2564ad307a452acccdba838fd285148e2bd0d51c769c4b018719f16d69fc58cfcada04472e4790e87cb8bb13cb3b13fdc56768ad7624b4a7c654a4a479a1874f7c1632c659de99bd153e6795671aa1360f8a5531dffa1a0275ca796fa12f3255cd978a67fb627b035f0750e011174f3b217010b5b9a2aefd2a4645dbb496e79d334bc8b44223dd15e6d29fc8a5c7b05215cfea2fd1bf733faa6c487a8bb96e6c474e2a494235a9c9dfcbd43ef31df2de56626994d2043f589bbbbd452c9125b68fd95cb608a4fb42407f41c6e7af1448686134e5b7c49076e7399627c60bb6c3d96cd0007ef508bf8cb7c53c82fe033532e0d999d74966e0060b540e4157b5d660362eeab7313a0ad7e42c3bc03055629bb5b8665ad43da4e0d78417ae7698651f1856500000132030000000000000000000000000000000000000000000000000000000000fc5bb5e5f90742b376b3547c788b039f47b7f252634179e06c1b164f022327ad9d662b472fa56cc3b28e049b6fbe17e6b2cd74ada103bc6db97b8ea71568908395cb608a4fb42407f41c6e7af1448686134e5b7c49076e7399627c60bb6c3d96cd0007ef508bf8cb7c53c82fe033532e0d999d74966e0060b540e4157b5d660362eeab7313a0ad7e42c3bc03055629bb5b8665ad43da4e0d78417ae7698651f1ffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81a2394adee74ac4684f0dff883ba1a3b1b630481c8bd1fcac7bc61d8961e1e052f9f668dcb8f8d3a4dc699e9e21f1a41414e87da01657f041bd6a75555a4c0cf3a9fb1f6e6c74944106c5c8d542ad60adc278871ae0685d23a92d205ee38f89754066000000000074406600000000005c4903000000000043310bcc60d3984e1f7693fc34703107aea381ec7bb96d150ef8dd0ca0b5a82aa9f53bc14c3856e1582b43bd5b5cdf2d3288430947f5a0ebad33164f168e7ee5bc32d027528e36df39bb013f3c7f9e4a5e9e9fde8420a2df711cd12dbd467c3af4000000b56999808951e6516d332f55c208079bd1cfe840228e6d7d216f7b79968b737b336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71d8fd70a4b183a6d05c9a4a0182088c66342258342e068261979099a44a19a3cae6d8fcf00582bac42a5ed88033e9178b85e3610d7d513ffec3790bad7f4b9770b69f8e3f4a4eef5d929de86653ab9768af093a347d0ff52abdf73d76673ce3d63903956f9593c200258d2eab75ac5349a76f18e1c2d9307f2844805183c2933af6ecda4c608c1ce9464e5679b45852b8cf87c3e1a66751b7df87e67a391f6dc1e69efe387c472d948d0dad745381bd3186ce0f99f8a17d26ff6ac90b07eddff845a79d4152fbdd5be8e7fc53e3f50ecf3ffacf987dddd94e19a4c8fbade34e0b1163877ff1546fcc3d79fd1b1c27b76b9ef563ee1aaf7a39637bc949e5999ad6d3dbed5bddf7f8ef6e7c3dc7a6a0c776b91b889e0c8232d2ef811f497bd5b07f0e6ff666688fa7a78d3cea8f557ffadf0ff5fe73dbdc1631fc90ee7306cdebcf75179e30aed77770c9bb6f3a27b27d134bc4abf5c5a57387f9a7fdad9efd4f56cd34f5dd1efcef9832fa01f7b68a201e335da4ca1fbe302dcb356500e1866a8314b0f3f50fbdd2a6f2fafec3f2cd7f63f621beedf45cbbc21409260ed20a9b298ec862934f6711752e3ce9de299d37ac43b7402daa500b010000000080c3c901000000000b8cc90100000000c735916400000000380200003360929c0e0000000000000000000000000000000000000000000000000000005e83da41e7f67cd1ad631527872071a1f13fd3134e73d3c4086dff773b167395f8461e6c52cfdb6ef82aa4b4b5f08d6bd8ce7594f09fcda80ddbc9cceb177c35b74cabbdf4b5c49a69fd6d9cc33e4f105f637acfe2e2590f08f157cacbdc19d3d883010b06846765746888676f312e32302e33856c696e75782040660000000000207e0900000000005d777c17501df48de6828019247ac97d1eb42289546a7e737a1f8895b6b0e17953418250206b2359f5cad25a6cd5e9bb515ea730142e8aaada90b0222d7855b3ed361aac05cef9c8724e522f9d1a9fe6ed8ec95151d6f48ac7673104fc3fb9eff4000000cdb1726b446a53b35f329f567a4f391e97822cff33f421f64b127b8a7a610520336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d7120466ef8538d29dd176573daaeac395100a6bc352530ac12affc86b675006b4eb5c2439848bf703a8d23008c1c011c356bd15b82ac588a072906995f3d1732133390fbe2f71b22b59647b2ee4a3b5770448fdb06b48fbe52e1bf2afcf37b8fe46c6f78da082ee0ee68327c8370f7e9b9f787a78c4154f8523a2fe08301561b0ceefb8f9f2c20c41d8cd74b1d566f07cf3f395be285290203441c1060182800008030530541002ce5182229001109314452624d13d30205c4846320658048530088b43505031140e4be42788abb40053311bff48088029c4840400dec6d62414a92c111a945000a0a0c4c38581c808521f2a01982220070a40a6189130d253051da000ac1ac918265660014f59a05801028a80a40168413da82884c5003d595688a628c80243a18a3810213784024004251b1a491ca08f362a08264442a90c1d8bda925194ce4c030c8e4208108e40a2f0a0600261400460346040c060c8094d21975505d6278a4c4442a105c578016eaba0261ea18b82f082511d2c0aca644e54dd65582a181367040f28c5941672906d03ef46401ff7ed6c2d3fe14d2daa1a7ae6d5dbb4a914427e8f0e65d26807d97d799e25f56500b010000000080c3c90100000000a5edb20000000000d731916400000000380200001fb57a5a03000000000000000000000000000000000000000000000000000000c39c02ffa618b1fa4d20349e4f5b454787011b2c5dca077946f8fa541f612b2d849adcd4cdacbe972dd1c66c4554a4c298c620a380bbc55ec7a5fa1b979d9be97f88459f77083e57c44ca4f6469c46c972e8a6fd0c6241a5a2e0ed5d5ef5df8c6265617665726275696c642e6f7267bba4da9640620000814453665c4b46dad568d69d0a3d211c70829ce7c5c17549713ed0996c8743e6b55b3797ea19c0eebac07b0e163fae9aa71bc2561705e492dd206730e8d7e731e621d2d7039ded027d9910bd41b23f642c609986a33f46fb3187faf6a0abc1809811c919b69e9ecbe5c129e3bc6cc6811de879149bf856984cc2a5162aed445600abaccb10a1b48694f150de473b893184c8200c822abc86d3d8d3bab7918b55963553bf9be9d2144a36827db66449e2302a49c72837b3e793666321ffa0a45089cb5f6af2380686485c4a85aa460dafff2c2681ffc4dd2a57ad488e53e904734908fa7759d18edb7e58d54ae6565774b607fd7488f013b6d02cd13beb3ed2a41d983f02f7eeac4b7f4222474252ef4538b5b09c3fe7ba6899412839fb79588387fd75faf7225e9dfd65bb46a795929d1a6a83113cc89c390ef293f9b73f336157e2f4abd6867a7a3aad6cb0472e1f17a73f913822642688fb28944b9df775593ac8a77bac24608066588ffc11a91b0c85d3f078be13ff586f7cdc20a23473f7a8c800c039edaa2ea42e15be9dbd47638ff4389b0a4e7daebe365aaf47ddbc16d3737ef8f4ed64da4ff89064056a794f9232ab744f72c5ae7fc674890d07027dc5541eaaf8dc1edc8d8fb4d5c763053a53697d9e5100ad9afa1e9fc888cf1197ad56d34d0f290b5d73dcb191ca444671fa433332f9d451efa4623ccaa1ca061827b86eafc6f771e184c48f4a3ab88c44829cb86aa86516cddcbe07bb52957e926dbb7bea95e9adb19ab3f99ff83279b5e41dd5cab1b5ee617340c8b46536a4e0b60d7235423760c2a72910dc838457a5a6c2d96bb1fe3c8b1cc292af040bcc5fb030d407a283dab7cf28b5fc8f651afb812b2b138c2dc05c2606320fd82ebe8ca7843ab0058ccdbdac8395bd65df3327fcbe1d8ac52b5e8e8970acf53a46d1ffa4ef16a472e24746a05f13399a7613a2b483855e7d67348cc8b51afec047355d3ba2a1f19d1e2fe3ee7b5137b4d0d257942118700ce0b506ee1b8b0c542ac600ffa734a960b60c13e89d3f60c5de14e3a557159326ae0eaa2328ee3d57ee2406ae9dae30d2bda566d5e22a2bf051a5ca0485b32edb939b949a967d315c0b771ae169433c6b683e0f58e5a4d874e4577d8ec74ee5466491a61cbd96f3d8ae11bb3d5818fda22b5f7914e82ff54d868983315df52ed8ce53b438b6f147343af4508813063e68b6416ddeb0eb0de1c494f0b40211bdf757919a28ef984ca6091f15f5953e0c8250fa5cfe4f1f5e54acd9faa8b5efe29a5daaf0494151b73f6dcc9f8b08558535b1b4887d275cd3feac9424be96efd63191c6fadebe8825917b58a7a286cbdba16cb3df97f1a94c1e41260bc4980ec4ed34032e8c714fe1ff769f8a79217a4a25c1efc38714c68eee4b7f8088e75fc044349471caa4b7fe94793d82e46e81f7bcac3ee933c043bcafb97882ee20d9d45d7c459934926b3079411afea06ae8cba6f092824313ca9998e067051b638b77ea5b90fb69af4ccc66218945554d9b78c3a5ea25d7e4eb9d68bbb40cb99176dd8ced6478af77e10570e5329683d66a2dcddfbcfac27f44ca51e7eb5ebe686e3bfae17a8415a2a13b29149c4392e4226a31225ba4af8df06e20d34c0a0b50376c28e0ff61f55588f8d77e481a3bda3eafb6af54015a2fe2b85c1292d883e4b074123a873f7bace327f77b37239841b1849e87fcd9f1f4c0b5e02ebaac21e3fda7c1f6e5c0bbde58071ff0101cb20fd117b265a8e87063f0b4c0ae6342af61107c2c2d0c9a68b39e8e609dcaea876bb2257d5c5a1e09c0451782ad560b8be7489a4c1e446b1fefe710d1b5d5fb2960d05e931f6fe0b6b85d4a9d4609370308774952614e889827eb7fa6017d5ab5285494620d2a3ead19245e4b6d389d503e7fb3faa7d71eaebd63d106bddee15ccbf80221a12d4cdee182fdabfcb8bd84db3e84cfa6b67d20ba17b7f96f2c9a5206dbdb251094ea01b174f664e3ecd145b876db7b5f900e23ff823e32cd19ee8a2dd30265e196615c6ce66d688fd344d68ffa7a7ad53e1570e5849d06a9d35c26cd41edfeaba7c0fffa5e2e017876d4a10453c906ac9f569ebe129692d49e6d4bfa42a4fe8f0838fcba8107576fa0b970433e1930c575f5827593bacbf77162a8187f7befbfc427bfca2273d24ddc67d7dea6116a1f25a02baf10460040120b6570c01b69a742d260351e64c1911daa80a4c8ca60e2c94b275c864f76a27f8edd99ae770d666f359cd4596978bbc50151ef313955cd867e9b1d4a76d501bc9999c1a5390cdc76333912ed4a3dd34290669a44392917052b1867d68f5ddd332f64e380d4631ded0ebecb92d09bcd7ac2a6f5f39e251f6b1070d614f716e2fb95d9f26aa8b1f8f201e6d473b2ea2624eca1cf297934720ce8e708b2cd1b992a9296232cda34f470a6d79f0ae5f2025f893bd15028988e14dd8074ce97010091de70685584e28bee1963f58a262c85df328377cb0c5cb3f39fe568684439916ec121766afe27abe8fd25ed47c06700b8629f27be989ae3e439aefec3861d3ddc2eab0281868e35001e26f98d7bff81c63c22ecbfb48060d0d8d1235ce28d9080dd2de2ac0408d583b8567309c4dbb0318dadfdeca8b8815fb08dd266955a05101c8a2432530535333ecdfb4f428eed385fb25a101c10a1f06e0d921978f3ea9f999459c488dde6035c1a6eca88998528f8e144b36320d6bb688450c9d394c3089d509cc8a906abb6c43a8b0537707c5bf7b1a9a7e573829fa3c9a415fb0001ffa4b4227e15f1e1f22d65996933cdf20ce49ceff76834f690caf6e012e209e34a4e814ed62d25b66424d5a788a4efc7aae897eb12ae3e51665f478332181fd04a995696afa831ebd6056629bc066cf36ddc88381d3c88fffd68e3cdc1fd9b06105066119994ae81040503f1f0a10c4153a11d1e609adfb9018431c31c1ff2807faab0e7af0239488bc063dec1190981964affee89ab22faaf23e3c24cbcc7d769e7102208d576bd26a640878650ca345aa680befa367dd105b3ebfd99391d53c66afd6154cfe7dd8813fe39059e8dc5027924e25cf94d13a9fa4ba1f16cfb442c8a8d3f898d141d9efae49249fab1d05cb3f9fb900aa0ee6aa232911822e0c17998201c896ee15deff92aab0c34413d132ab731c682c9f3b3d745e6c5e18e673c16a56c4646ec0c2ca04654bab28bb7a5ca579a9170ba9ff3e5363bce737acfdb1eac18377e33978ae4a82dba9bbd4419221e58a10ae80f91067754051ad9c16606b72752f43ecaeeefd9f0af140d0d4461a3d890cb07cbe2a9b001571001fefcc7f0e1b92abaa097e1566d5340853515a15fe4256b83ffe2b723e60e206b75f27ca1b99b1164484197d115a93f85aada209f8ab8a31ce3a66f23c820698febb8e95ba96ac28fca74bca0d504dca4cdba7e85bdaf7fef7b0f17d4b6fafe4c3e9810ee9fc1a83466fc3875eb8e22b2ad6e068b9b18bd9f60f9e66f823cc52a2ea0eea5a1c3e7756d82811c9da030bbc3a51c1150ca8cbf5ba38b106b185e0ac4331e8a0d653a66cad60427efc8b7dbdb817999e346152c197e1b2d61a5a9d7f2ed328aecab1ffee39b76c17dd3577cc399ac7c7e1cc48e4fac0aacc1451793db4f91b593f0ca06236425417238ea6d40e1837a9928af864d8b34fde1cee5bc2bc7e69bb9908c8de49df8c821f0fd6b497657b4ed5cde9502e86ae3e6f7c15189a96b31d30f59faa760de83831397c7f99cfc7e23f2687aaf2ae64deba1902f491299ae927ed9c10ff485f576cef160dd32c11e33003c9eaf468db444bdb715d97acc8df5e08e6aec88d91f747e897fffad73af7e05b0c5cfe23deb931f489763e876088841e9d7358c94619229ef27149b51f0a322200c103e80588e1f6f31a47f40b3b858d0995af11b99d7baa4c7cc145d58e14c240954234e32691001e9cdcde67429cad3962f37fd84a7c61857540799b8ff3d3cda254ba05880e680230712a0618054dd0c89b862e419172a0282277865a2dd45e14a49e31e73db870d70f238a29546e54eb601cc76b8837ceea671faa84f096bfb4b7eded007e12d2efc4f9ff8a421b2000a75c5a01695ab33f027429361fc9f46d0bd883d96a1f9b4b329a9c7256e45f13a298590c0ad15e3c16c73b541bef836e81ba5e18c844c1165fa23932c40287257bedeea72af52893990bd5a6bb57df63a2b6a1565680945f87326e38508918c0020e7f8cc2a26e381e34d8197cc45e0dfe975331d65494aeabece73b741ac9b192e930439dab6b62b91a9dac9f909d78111dd62a5f0561f5f47a9a60c5d55f309ddd4b7b94efc87dfab8effaba010041abafb8757d0f681e1a25939cc5ecf764bd83f2832653feaa0a18d86336aed2c73c84199afdd03171e74fc96b865d0bf7f4f5a54c15c823f27b209b5d34b64cedc5baeb0184b2d9524b012a2e4fd70dd539db32f6964c34d16399a16c5499597423149a97723cdf5b5deb33693d456213793adbe52ec75ea8934e38ecd9299ff8d57ef12e9b4e14806d103954b86321ea42aad93daf0ea876befa5bc2a7659b3608e9efff93a7b5201478798d65d892aeae9ded2fad2ea4007c0cfd35727d44f8ca4c7a52b4e331621e7dab1aa1f7aec02c7e7c3ae36489b421042a9f331cc609990c589f1048c10d1ff1873e9a871477ec91acfbdedcec1cc83e70447a117325ab16b1a69389f4f786acd857064e82ad1da1257e3ed9820be84d6972a5f90ccd96c6409124c845a3feb23a7b862dd28e094e2620ecc39fb590e6cb7444e66f202cf8922ccc47b807776a672aa35e4434e27ba331d0666ee19b472556951fa250b021dce47ac13a33264fcb87597ce6a7d66391d19da9758ef1ee7d19e1f774ce54c5e92a487735cbffd941210fcfc8c42b7af9fcbe376863e4e919916f0d0ccf8fd05d1d7b3b41401864f4c179bcbdfff434dfc4dc4171d35ce0887a0ac8e3d17f150411a09a74e02e47fb8f537f3add4377e0381015a79a5fc12fd86b521dde790030f0ddc7cc34305c0bc5e9e3b22460d405a3cf28761c0e7ada75fc69d11430c04bf856870b689e40491f49f76d18b6c62ee4a4937d2506e5658b2e71adf7fc9aefe03e6fedc0251a99760209fdad863928ff8050c39c8abeced80ecdb13fe10f0f65045f2e2d41958e49bbb4c4fc1c5fc15fddc7644e5366cb4e4416bb1a6afda3a8bcc5f7c51ff01135f7643dabe355f4cc241943521cfd15ea8c2e51bf44e17354353436ea6059f90e393790af9a011bda79f84675f83d3e4ab18a7530369a953490c20ebf4430a5398bf4738abe51a6e43974999d316259501c60c8d3a4efcbe8177833c67658921351d44588c2339704b9d6bcbe30f95b94328cf423be2fd387321e447dd5571a0c1992d091f4397fc47a835e25c6355488cbf4e2a06984410a8df4fb8bf596927531d59bb74f72e147453de54b4b82c99b836fe255878b4156eca6caac99209c9f0054f32c2138c9ecc834a2640d8ea4d6cb521bdc12f12d055774414ab86f995032ef0bf03ad45f1403161b848bd4ef4400e1778f32f5cba7274ffa117a1f3c96fcd6f0e387af6302ce40ed69cdb50b88c76388a3b80c3954c710f6617e44a986cd65909ed542614c1c6f80da78461192553d6e077e9bf8ea20b6016cdc0c995ae07bf473df39af8d0dafa160f252d58d394930d46ef2b2f0a7d1e48d8ef2aaac8a9ec0b7f00145922883de52436598fdf1fba9f1283d31b70ce0ae4daf3db610d970ec2582863e40458de4bc082dfaca451d756ef83a93baa3fa37b3f82ab8cdaa487087eb9175d846a789099e344b2ec58eac67185e6305a81f5f691330fad31715f8fef45e835a9da43a571a016a35bae46b3415ac704c66bc651fe079c797786e047187eb8c3eac665b521beff69db528d5a49568f2eb0030ccd6d5e19ad4adfb271ed46d44024356808f77e16573c4f0aa225694857c34c5f00bcae4ff15c91bc5917502dcb84b78f04e2627794268b54d9a670f0b97d9cb3a5ec637c0eb9f0922a70ba445fcc20710c56b7b05b902262c081958163c0036ddd7aca4daf4814ca4fb003b3f59a76adb7390155e0dd635b8c04ca59be1a0768463d94f49a021efb43645da70770e4b2f4d00bacaa91df4572fdc8903ff47df32da286a5f14a3ed8717e537b640aa123f6b64e5db9ea7e3abe9907fca059493075091e10815eb342b85326d35a5d978515882b8258c71ad6eaf9eebac6ef8284e4d7925d40b48fb1c4ed93ab6b4bc06411cc178e8ecea37cb50a7bea428417ab63dfa931f0885ac82f5330764294d0297003418e70fdc994adf9d0f23486520b8caa560e8c78251fe9c95861a45050797db4586e18d968f6104dc18c6dcb6652ba7f5f8504a76cdbd56c2fd9bb5c3b33384ff6718e9cf70fd97b62a4a2384807a6d5e9151e890ebf9e797c61b0eef785cf25b6e1f930320cf1ed97cc43490f3318d74cb4a5835e742f8ff9abba5562e791eac25fd8450b4f5458fab279ba50b06e2902d04d1f63dd6d08f515a87b1f13822f7fd88e464e384b2ebc91c2ff0a834655c632b5b7e3099132fe6adae081fa6d756e57949bdfaf00a3474b5b4b47442d160c66ad76d9bb755b144f49553feac5e772dfcaa944a31f4ecfe989ff4dc092525d7e95eeb938c87e22de2e18de8891db8fa0aff02dc0c936ee1c5846f454e6dd5a2a8a84111f213242ca48ec4a0ca42de208114b425884bf754f9891a511b6e149009346e2978a89df0394777a636bd6d6cc91cd06cd1395d9c42cd5f278e1ed46ec4799910d6ac90fa9fc346a09a83a27a096602b4269da59eddd4ae1c2f3f30cdb05131399cf3c50c913c683ee1a95ae748b674ccd3ae95b037aef9c98bc4693eeb2c68ec35bad4dfe85ff73b1df1584d3c99ca62f44bde2d01b4a1a20ed9e8309042005d373d3b93bfdc4ac7899a2f4fa9498275caa522098e7ac5d756414e3acbd875643c2525229105cd82a32669590f23573755c92518134dc29ed20ff7391a7d809a4a90d4f3ccd98417306079861565f24088c9f7145f44093f6dc62ed87b0b877110d22048df35d11a9c55f0242a1a4671ec29a9089afd2f394cba94281f8c21f56ae82332b7b04a61d99762498993fef839a27bcc305b47f0746f24394920e5ecb28ec54e49e6a6207c63fdf445b561ae777a5af4717bf84bbcbfd27b47f5a72308e46589dc13056956be4ae308bedd8e7e8f0e796679de5855aca48d26dad61e97f1b66681ab7d3277c7f77e1d69643db6ef966831fec812c326dca60b33f317a1cd6d055aecdc40bd5bd2199ab738595dc59d4fa794d63d7758c06a4aac989686cc8abd3c63122f089cbf5398e933313ccdd960903eb597954b2749b848056b996f5949ed81acead2823d11de1925c547b07fdd7a0764e65d42ba4cfa5277424bd750b6dd6a446752b4b8821949fdd4460c3ef0340de7e9687f468a9b77105354b55bc5eeffba2a27d845f79b7396446353efa313d4422bea82d8bcf95897b3f15aba174e91059115e5e0bd02dd9aa92397f35a424e925c297d70be682f17c470035b58ea2f17703c86333e5790dd1630559e4d4a0313cf7b069bb2467ed1a53f4ec4e2587c49d582a4b21ea988e620b91bd4647297050d64aec86b628bcbafc2106ce8c6e8f52101c0fbce580b18b309d3fafef0c81a3f1c7ffc66585b007270b3868a45bf9168ecbf82489324ca7c1feb0f99b27f9d9a294481c95d5ccfe1dbc888d1e2c4c506d375cbc89925113d25c47ffdf60818744c832a7abc4ab36dfb4a13dff1d2830e9e6fe3fb843a442303b1eb8cb8778ba9b3fbb273a8a91f5e19e09fd2a37738aa63fd26a0b630bb3b36c219b79831562877b484273e72c8b4320ab00d328c3bb1854c99b6aa8e2ee69d767cd5a205c8982ff75ce1a7a46cdde1651e3f8f1bd79ed3eb595e9efe010d59ee3c3fa9470bb03c285389790f8ab442884e4d64b0a479066e1f62f2a1561e0012e44def9309af5566e94d68e4f5ce455ba4f9afb0e662287f87b5b96e0b215a1b9baeb8fb46a52e711afacd1ba7bdfc50e1ff7305ab07264186c83ceb77cacf008b6c10d56fe1f4610cd05844f7e44af4f08e7d7d0e8f55d0f3734956fc9287e2a8294102c2d97ac21f9d741b32c3eb9086bde7712e164865bbf1a84f14d48e0b38f98ef54f06af33c916db45e6abbe3370c9e47c5a5f5cf73b4b784e47bc3f5574155c804c18ee4954f7e89c50ae9ba4d03123093a6500ded8a6118f7dca1fcf62614e68f38d2e598c54a065f228eef188cb7aaf1f41df6f3d4d788a88d204e9e285034a0c6c5b6b894e232b844a4696a3ef7d8f0811e32f6bbfffd557dab2b588eb918d8443d0a9f4a7c82b42c275bca9865e7ac38ca3e49dd150fe2f01fa8df60d6f581f050b3bbe0ef416ff657db803c0c4995b9b871a38a5fab90bb90732766d35452dd0ac64971d75a65d744baf6ca2340c26934f6527c29665ef128f17c20d8c1fcca12fac9d898893a664c600896a922ad526c6283050ae67863d2ec2f47eb01b1a3e19531a2213078edcbb953b57fe701f0445e95b6a78e45d1ba06e3b9077847e1017f6085f75d3bf0223c98fd32000d555b73e6c51ab57246e15d22531693894f793cd27d8fb68355030b0f7a357ab43192956b96afc377de9b07c41d30a6a23f461c47f40d5e2a023795c06fda75737e2a5143d325b86d62aee8500d1a76c1a96269817f465ed46b40140b7d892b68ab40d3430cea6f598b8279625deabc631a7114e99e43a36c83fb7d37a70d742d297b973fa7e0caf2b47ac62f0750e0c22a59ca5952ea74f0b59e16a1e3ce1b391f1a9f28345da7a5f0b37064ab736772f7941bc9b7c758a4c56f1fb5455ee551f5e9e02e8de051e339bf90ffbfa75c45319cad15e2c5aa87b98b604568dd1eb46c9b92d553c5c4268a1a2e44707b3e6538ebdfb5f504e73fd80b0d971a6c280fbf80a35a4723b9e1db4566ae59354322f6a6a2ef45c60ac12ea88edb34c90fbdf7b8bd8708cab7bd1a0b29be454c3479f2629c5018fea8285f03390c355e0accd89f6824d449a38e6d0a2ff8690da806ee42530867b3f363b3d49e738df1563c5600702ecb5bab1726ba55fd0d4ace1581d4f4108368b24fe4d4090b371052098c4974faa7e46e82cf07589822a39aba6b03c2f19746827fc4d2f2ba82df5923d5e2876872d840b657bb2646c9713cd61a83510e5d00a754fd43eaa7fa3a2509a74bc7076096b720b73ea207b4ca9aa638b78f4c0d4a4257fa3d3de17c30507af0a058d99db8706820cd18dad632b954374503edff3191fcbfc5b2b55be2b0b7504de5fe097d97147f788b55f6332331101ad4204cf5b18173d4d0809c7d9eec152c5cacc981b25c8aab74e3adfc472fa13e6f6b3212bf2293f96a2482ada1f4ef9dc524c2499e970eb4496da67b6948958f998dcd398b3aed89d5943d1529ffe74cb7a7c2df90043a24ec03fb8adfd9ed6cbec980b54d199f665e755060c796c9351353a23aa988ceedc8cee0d73be4ed1e3fc765edbf7d8dd5e102cab4181e53ad02a5fdcca3c534f9110e4e7f292f5f4aa5c3fa49ab9877cd3b1c6196f62ccc3f8fd616e08eb364faee03e79b96212a1f1887b85b3502ab1cc20df3480d71aa3db7f60ee2a3167ca7a530698c998ac2352f5043b632650175dd345a3bb805c2fb200eca4612732d72fca8a5501d73777b3bba9cc398f16ef01998e922d41ba8b0bac453b80d453b7ec869bd0d79e9a87cbe0fcbaf47a11849c6695f3b877ec1df5cd248bfb2296192da2af337d4767bc3008ae01b8228d94efd3b1adec17a5f9b2a12ab50175246356edd18bd8d5b363d1bdb7f58943d8bd84d91f1f324a74c654c6307450612e94635ff12c03f08ac4d9602e231bc81eeed25901c51e8c786f66448774e8d79492af9721ddf0e37a9c168287307f2b519864c2f897fea1d8a4b53bcc9b2c5ddc91c84b8c8b090a09da8fee5f148abef2304a840444bc005dd7652b89ba5576f6481891a8a71397348ac7829bf53e3c58e5e095567ebbc9848aca8f2b8d3b6c09af750a10f6a47bcc6a45480820742de945173cf4655d93916154597d1b8de6b5b01f18db2ff6176f0cb89b68f62a1bd48bf7ffb44274c599670ae58084d57d85f244811901762194be0023975a453bb177f136ad9495e9f24b0a781da39ab7832855952722ed031fd1820aab81752d67f23f30a6e3301f3729f6cb068ec65e1ceddeec8b2c163e8624f574a65cf8e7b81570277a08e035407611bc2b136459c96dc986f140dcca94d6c69784c79ee9100ec11d240f95c7920652b63d056b35fba4582471c23a9e5dfbd717a689d9776fe49d1f8ef8fc43b530597b6cc734edec8aaf1c19138f7c65b21766ba935b11ae420d2fd0945cf46e15868805dcbd39a9223c32176cdcc19f49db6ee857aa5b6ec01185255871c4f65edd837e51082cf069fbaf7c841f13eb91cf801ad1de660a0acd43fa5b2a7c49bcc61b744b05d25cc605c81fbfd829032ac6bfb8f328685938eedc8919de180badaf8980ca0745b79e18bfaf31ca778080ea486602c2f9b80db583b32c07353f23b31130770b37863f310ac5c5a9560b57430fbf5fc37359e66735c5867012f7059418714a76fa7c5cabb914f3f9531e4c8a0ff7f8bb5bc7b263660982be7e50e565c0ade5633d94f5de6c71ceb4af1ca4ac2137bb7c02f34d88860e312681e195320727fde90f17f982d04076ab3fdd2357fdc2037db0ed17506f194426e43b065b70ff8460a6234a93d0a5c54024e1c7593815c108cf6d545718b06178fdd7dffdafd222c94f649948e1290cb85f8b166d82b7ae97b3e3dfbf3d0f381318b0a15eee35bb3877e3b966181b5b521aeb4ce1bb11554e7f56d9065e4c849e2046ab6470bb9aa3fc407b0b676e60a60ea7570b3260c7a987a5b2e949ca039f3db17608b6586c169099482869b07f7325720e27f56d07a4656914b5328648296fb66bf95b76578a8fa4fdb83daa7a395008149fd3cdf6fdcf1c80a236b3a1a96e511898cb24b631cc56aa7c7173c36162bf4c2e4f5afac8da6c4385ae6405e88b25c719a464b9a6eb2a3453ed21f62728750af1ebe768c7205e8bbbbad32f61e1ddb6bdd2556b5b21bdaa11dd85717b5eb28d995889ab0b839d8c4a6183d3804cb4403c361b0b1d27bd0cdfb98631ada8be88e17ac77f2a697ba4fb4d98d96c01400454e9d80ef89d29139079ed143e50151bda9ff1f43eeadc6cea6e693d74f4cb1cfe09696d396c25ff629064aa2d8fe449bf9702b19634605d66471b2f74f6daada1d0528fbe4c76c5ac2918e48f0428f0d4388073784e68fc2c0cfa83bd1787849fd849762ad5bafe0ee3ebf8b0599b5a98a520a5be01732d5031bf92ad9ef0c235c582f4f970a502dc4e38ef8bd6e7963731a8e1fb1f2d8bda64d5989d9b8e8971140d5fc36ca356330ae603795e61ef15758b603b9cc62fc0fd03adc9988a7f62b6a18b60eccd1bccc3b27f03dea73d9300f38d7dc40123b365264b04aad43e6857ce22584d3ddd0646e318e204412350dced56e02bb8f30ad1cc553be2c11c989ad8969ebff9c3be0db0ba9cbfca59e7b053463a5fa16ef00c33c308df36f2a8d994e1d1d12297eca66ebf0295772d0e9ba8e6fc8d6fb36d74b86c4459ebc2001110da0b6273d04f8b0c23a16f64e405d72515578b0f2111a7e9c438fec08c60e21b42e396bd9cbc1eeff6e374978fe3e39d75e8fb3eb96a6fd485e4ce9361875470a5c3ff43a2efa1a00a78fc104bed02130fb180409ff8d2a8472285a0016c50a9a41901a4902c19f21e2c120044eacb6c48d3ca1ee79780370d47f296d8cf2b8d473b0e0dcd5feabe4d1d42ae77e7264cba987404969dbe514d2b1ef5b95e06b09d2688f2503ceefb50d21fdc4a897dd6deb6c4ca27eca219c58c1182383a04f500798a3a714802a2fd33cf2cfecc8719d925705e4fd8c491932131413b9f5498acd0463b02d4e6345a4f5ccb2c95a9ec60ca4f6acdd6ae0f2ab1c1f78ba945fd1c8d0d77b374281b49ecf0fae9b27afd520e577c01460bdd07ac1c521f94f3d21c4a87871ea9dd103323ace0bfd122a4993cde5584b69f58f2ecce55e424232db799bf2441aae86c51d22c8c9f4d17b94f786157a07dd8701a1dbb2878c3e6b3911a1d716160e45f83e7565d364d4b3ada1374b7696061d42552dbcb7647c8e4d91ad3e1846cb902c373b5b36e5a09b8ef95628c6c5f846e954d6c02e446210ae89385453948fe1669e52e185f7104efca5b505b14d17c0e6f9719ce4b22f71da941caff7827a8311a0a366afd8d274c76ccaf108626260bcee8f9c0f1d8bd5f979b6b8282103c2af61aded55e0f5a80b2b192f12c42b6929364648d9b4b5680b0ed1a77a21086910bb0c041ab86fc2b25aa395ecfd5d255413eac364998a091181ecc091c64050fdce03e6484815e580f21eb07e6267719a0d88b2291648fc9ae9ab444a5de7e5aedab55d27ce3f400c7dcb57bafcc24a30daac9eae10503b52054ccc8b18220418a850392bc20ec3f768b3a6a236fc237e0a197df2a164a3e49d4133423226783f49c7dd07cb840d128eba5316878e0f85c3ef30bad7ca5ea8a681ac8f6a216abb0d90ace55f37c7179797e8715c5640a0daa39981fa48ff73125f2e1ab1591402515f7ab7b533948d7987b3f237acb2821f2746099d4b714fa228fffa92f42d0c9929e912ca5eae07e07fdd35e62de79ab35f49543eb0a03ac1acc99570289106966173fbc2d594cef0da9da3ce46c046802c1716b380a307c10496b2bc330c2d146f62ca8d5dd254e58fb846bd1a3e50a1faf580735a473f6e40ce67a4696a4612098ef832ef13a82e756bf9b6431a598a12ca8fd80e1c1c52b6e66ca01f6331ff5bcd1821cf35df7e1288e3d72ce727ded3ad0ffee267e28737607c70aa57f72dc4aff85027dd2095866d46b070b26eb4cfaf5b2e5591e9898acd7be659d7780f9de34fd04aad926dc2cf06cbf7992965e7db0ff906029eb798f09924500a6ea5454425783a4f8f6cf623753e36f13f1487d4909bf552f60b64467def6ba257ffc25aa955b46ae2378025acce6a65e90f2ad6474c09ddb1f24ed893baba3facfe0033fe4e5649357d59a4077684a69df61933829bdd84909ab6d684ba7bccc57b5d4b67aec5a1ccfa2c858017c579cbed366c29b6cd1ce009d5879ffba0c650dc18e683b9610e651586954365d8dc567dd0a80f7785b3359e6371e699d57c61c08b9f65be0a23be376f5241a6688b918bf67f32e4576d58a6af7851edcb66b6b8745fbecf1064cc60ee6bc3de69b18cc411733e9a6af08115c2049018342146a9e518299b1e1631d9a2bcda23078ad50fcd658666cc7573031dc837d59df6836f02583ff70950c495b82c8ac1c7c1e15d9c4c83ac8fd9dcbdb44c81120f1f94695aa903ce6db48950003a556b7dc06627069806e71398860c3b619f1060a774e16f4b6dbba5c6c831a8a95f290e17b178dfe3f935fa9e897559e2539e4ba3eea81c61218b26c931c8a1224895f1de6468c97a89d14e5cd400845900af012b4d4d6e29f8a79215b052092c0a9e158e43cdb839c176d75e6e39ee6083494547cf175408d7d2effe17cc862f1246be9434d9e12b490f186be8f6ad7d3c7b5bd068ec6ef7962f49207b05af20eb5aaf7e99f80408556177c7a186b7c7432bdb577d7bfcdf3f485b91a57b60780d4dc41def326e3915a319aabf3e82a6b9708245648314723d2a331974f2a6bf02cd1af9dbbba3ebc42cd8d743724a4cf20eceed48902d52b9ab9f3c3e18f2377970a3fc5c194bd4cdf57c51e2278187b0e9a57f77ccbb39b15d7bcb76a84b0defeae1cd30b59f1c1e41f78f665e6d0a1de233b6d37a8bea9a3bb7fccfc9b102ca6fd636e48a71473c867893ce71f783c3659650266911965ad2ceb2003457a5016281f672f94644c5b58d285f9784e53a64021f3f48c949db5940e9153bf0c34d4ac8ec2628eb792535dbbe5d4547f97606e8d0811a4a342fcd95040371af516303c686793e16b51c8c107b6d1f22b60fc13ec118307aa1bec5041f5d0a9d6c7ac570632a609dae75d58a9b8004873b5f805a0e08482834477a8a9562482c88a9288b48afc8b2624b975f7a0637a5da4851cba6e5a751b891c46f2e2d818f4dbd516b7e6b46c83e8246d0aff2459703d9376138858c08d86ef6d6f3228d44218eb94244698a0bc448c70c340bfe857d4f27e988fa7467820742d641d5fe2679602bb5a146549e0e3e67fb6726d85834950e5c53dede23e0240ee9e3b26ca6cbd9c74562d77cfcf94b4269bd5cf892698a91c3ae42726ee9e07c69e6e38803f6631fd69c2de4a20c4f214a774a8b99eb737b4e8da5727b9dc0d0915c7eee78b1bfb42b9825b1d2c4c9442c952213d17cef7c181c23487149b5b681d7159ea45450e0f25e71aee4b9b50032f86ffc9f36ed9bd7ce63d688b9d8c1f084639bbc7c5262e9e0bb9eed8f7ddba446ecdca3984cde5d0e6bd1195226ddf47c895a64b44f27ba82218c48eafa271502f0705ff2e6f2cd291479c623b3477d67712c94902cca20f4d6dd7e09b1d252effa7c3800e1739f1fc220b91ff440bcd4500176a509889a104944318fd4bb4805d748b8a5a09656e497b46e4ad5ee6bd9477fc41cca86b66014c4dabbdd2825ec7256082774a6fe9ecef481b98ecb3237adeab1f476efe315fedc0d82356f60cc17f8ec26d9f565b16380f4d93f273c26c22f2a2c25c2b03e6ab418cae19711b2cf47a297f51dadab1dd129b0cbf9883553eb7f3f052a18a010f802c2d4d0fb40d891e4256476799d7e11ba0efda9aad41939a1498cc7db0198b09411d1760388527bf4a972a7a06cdc7d211bf85248cd0b783624e5c836c2cf3e1406d8427001ed79a8663fb9174d20d2a6c7adf02b5a0e1d4f7446252e082a0cb1bc524cef2dd07a9d5ffa7bee2f58d8579add29521a9ddc944532622424725bed49f2a6f047a1c770ea9bcbd8b9bf99e3e7ab09e8289b495780a2eb48ec0c45430942e7778dcdccb1de1411d40ba7de1f29cd3270d63ad58951f58275db500eb7c7781843cbef8360837a200b9dae2ef916de0c7c5c5e4c99bce7c2b0f4ac3491bbbe14c01f9e09717e7813beaf694768b53ff3e10dd2bf72ed87d239d8a7c9be4b0e4cb05e08bcb8d93819e197a462ca20b84ddfc071566f4124668c6c0f3f821fb2fc49d1587b58c87f56d3bf1aefee1868abcf44968cb526b7d572e9524bda19d38b57d55a13e529f457e1e2b2f8141396d01461774e350c1155320997151e870cc57dcea9dba96ae9962b0da0e26f21a55e8feafb8ab6383620d01c2b5564bcbdff7f79cd43034846f6a2b20b3da0717f99d394ed1e89349ca3d08a91e5f9595cb8ede82e07bffa174a1c99bd34887850917f10af5ade7e2bb7b1676b86d80e68492b838d6aab7f3f38f7463f2b944c8c2e8f050f93dd47b1ad02e3d7d3b4bcff207f6607eaac83aac5c5aab88cef53f6cc9c25ebcf8e4dbb0027ee977265e85dad4d35a70af240e1714eafe427ed99e7df48dd99c16e9e9a4ec56b0ef79b829d26590cbcf396bf41e06952a3ed7594837b434f5b90c166508aac0b6ebe8141e177e60caf14fd1acdce80c56cdea4182fca2da0b30ab58cff9b80a73302027f19aed6655fd9a86f236bcf134917ed8d7525c3447aec2d2207cb6c4b6761e885b59fb113824188068c32cdf08e973e0fc623e67fbd5bccecbf1ed00a0012df83dc254ebad178b28601d8f8eab90fcf97ff9d0189f9588fbddc7a1a7ba27f1c20427c61a46bdc2873bc8ef8c546503bdced0742951e3dc2a1755f1b0f042c14d5374d68310f10a87fd66287409129ca260d1e9aa34c0976f8cb5bd8d2daaf2761b36a5d3001bcf5fbe1c9b2b3c2b59013d6249a97f1708eead3eef3958ff9086e58e027aa039887b743eb03e02af6d465935df9605072207b6c595f0d9ad56896f010c8f7014cb9eac8f2187ecbe589010cc6563c2d9799ce3e10b66c546e9ee22e814c80d911ea853de53e83190286a87cf262d96441825ddfa696368214fa6dc5658e2c7aefdfa1644376b467bd295c9f1ac597c3a9e8011f03b02adda1cb0f77705a068d6ca6de5eace04fd4240d7972c777453e4f502f0f8d6f7861748250e448baf04f53ed5192ca782d008ed4159215c1031c37876e15a28988071384783d0983bb111940b9881f9c3b4864d2d220d742f9f1dddcaefc58bb9a27d30142b67fb074df8e9324c7bd3452377b6b761e2ff614c6f00e476fefd5396e6305101926fe8d6d48ce6da776b839ed7e1e6e64ac6bfd4dc597c221bb813c741912ec952a1611285b0a001adc61e51b05715129f9682252cbc8d40228401e5b8da773a3b44b23115d908ed8864b6632e95b676914634f4e779b76c4d920b0ac381bc348f2a7b496b90a4306b53a4ae2b8ddcc99b5fe0a10eeb9dc2081649237d24d52095f388f0baf408eaa1075ec09da6eed829ea2031cf95ab4365c9b73fd3b37305aa3a08964c995fd3da9badb11751d98163778a02abc1a08e1d52a4f315224371a8e582bde2ca33c0515d238927e1ed7712f03724b6280ec30f71fa84a30974a54bc0fd48215b6f062216407db840ed952379fc0a8a8c8a24bb1cad4c6f25d00e0f5a84252c3b9d11c2646de4b17cbf2c1cc6d651d3d479014258da22d75789291c510d28f2289b947309a42a0d8ae0f44a173c4c9eaa09893a271d8d7461a774027c234344c4c230ddaa857e1bf4dcd3ad3735f5b4d3448edf90c062e85055588062916434db91a0032c35b6d031425ea9eba1fbe4b3149591c90b5aa94338f5538dccd2654acfabf47daa81da2909f0988ddd16a61b2d4f6565ca852d94a1332f0d0c87c036ac4a9c867ad26030f216e054c9402a49fa5b406eb658e5f0ae9652c0c4575f0872d6065c0264afe7320ac52c3bac84b7285d0c07bac6eab329fdc8131604afd108707080e8df0375dffbc5dd180a798a327d50fd7e2279521b2899888504b9a33dcdb71f89e61093e5f128b5515f00eba90b8f0123f4edb0a485bc1e754e706b7aadc93d89e72e37df01ddcfe622a9ac8e33a4c30bfb7ebcd14296bff62d931007e62c97690636242af6d9875e260faa1d1aa4de4d906c679281d298ac932818fcdbf1ffef2ab9287cdf8662b6a6870f46c497d2364c0cedc1001f3d3ef7b34843f74a1e573a15d91e00ddbf851b3802f171288e0f2fde77937efcc50c2526c5cce34ade8478b148ef19f9454610c2fa62d8cc3983163be291b748dc4ed563b853fdd82b45d0533f5d5585b8d25f6c08f2ab378b803cb0e7802575fbbfd7ebe91c429db8766bd825f3b8ff98c76cee1a76105e2ff7685f4705499108d920dfe2389c2c65222f4ad435c78fa86ad94bcb34a168328161f74c445c8df82f296c5a6fe90d40c0b58d67dd0a07890eba26e2e3ea159ee0265067cc64a364eaaab228a60a9d4a153327cea5267f0aa7d6767ba2109727c244db2ac2d428e1442c200061d33e714976203a663913cc343b973a81b47c0a6832f5e36810c31f2e5fb9726a2a2c8bc7eb2c052125b5c287cefc7362c646c50427b721781d5fb006d018683ec7cc115ed664284748147adec635fb1d8d7e2f355239cfc55a325865523b44b795d389b21e93698eebc368e175b69a5f5faecfb58b96759b7164f193bbd5d2ecf5abfa2602cc23697cfddc6cca661ec574ca2993393ff985fb918fac4435f8177f1c84b8b51b98ec2c0a3e4c36fb09a181b89d93ff4082c9bdaae020a647728ed02ca1fffd408817e63f6d6f0d588873a25a3b8c84b6b6e9d1890ec888aa75eb293463848db0856e34a92be0183e2eb6b06e9ae045d7b9bf9714649fe70a1a4a0d348dab35962e42989d9c2ae38f92224d020ed5f851a3753b581261da8e2ac9511fe1ec0bfa29d3dfebf7a52cafc86ca47c3d25b89d850b20dba9818b375648562e28f93efbba12cf14b7a4203eb946d497b2db4ac73952e72064a48d6e894a35e5f2a82713b81eee2a2c754bc6ee9fa3ebb180c6bb438b9148c53f40c5076098a89a97be4952690c1f5635671f6917c34fa089850b77eb0a4b323ffe8abe46d9f16feb3fcfd7f40f2ded29ff70a9debe2531f343d0e1af3b0764bf5969d8b9fa03429759c29d22701a66bd246c6ddf5939136ad5eae6fa8775dcfcd28cd4e42ff7c8e05a5cdb1d99577a28a4b37aafc0d3f1553e2d2f3a31ffd3a1179e0b0d4dcc248b3b0ad89e3379aa1e404a85a9d33e4d332b970391c22d72c0c128e8c60103cf9a1ebdeee02843e03db59e1e9b8b007dae8a5f12ba87744bde58a11a1c5fa8e137dae0615b7ba3f2b0edc6697141c4b5e4d2e2c00bdb091907501ff54277e541ddf29897d3b90b45de171a78f54f25d7888bff7d0c5b0e3b061a463a093042a9026cf5112142cb504f9906f35cf99ba6726f366315c01dfbfe99d7ef249132b0c3a687dfaf7da86dff39929ab822328798f52de6d546632bb5b866598868a8cb3bb366fd9da63845e2c893d992201349e422e5c912956f2c21ec96db9a7c27c9829f1c7096dc2685ef66294f47023bddc418f91a211e23b25ad2991bf3cd62a81c4511494fbe06f7cca4c5281e14307e52f9da671e7627de5cc5c089697437bb683dfc9e0dac291d47e18586e0578e1d5365961b44451e282f6a54b928b514ec459c54c96e18f98851ab7e15348e34f47b932ae50078019f5d45f42d36f0b76fa4a8f7bb57952374c8e9ce09020053f97e818e2097212edd14bc23e7a165296c4e7b6939fd0720a865e05029bb7590f213541f05cb8edb197e6532b88741eb78ffa6c1103e7be4565111ac12e5c3d34cf595df0700d2ec64d312dbba5018218cf5a2b3e571c79d89f066c538ce63c1049de02982e7e2589da2eb5276a751aef35a676702a8033d4b491e03edf1a70d9fb16c9808a67474dccabc91981d6a6824f26441118059f1f60c72c0ee2225fcf7acb78229101f02b6b8421c9def1306a9f452e304ccfc0f715de13d48ac05a3684a130da6440838a789e946dbe6c7f44c44ffc7fd7c77b9497229052882ecfd0898168232cb4d796781d1054973dddf04e09577481baf23b5468b95a5416c76f28396411e7aad4cea8046591f664dfaa3af8985727ddcd8e8e4b87308ad0328ca4294e8b94fa41b4c2d0b137f93e4d9fa24a301804f5338ee5661eaea06be44df99db421712a1e6bf81713548807beb5aed4a1d78ad06f5c245564d377be61744d0a6db264741d50560469a055a1b8593fbf80ca2f99f819290043d4a68248d47f02432a6cad46b49b945835b230ad0630bf1fa12f698804cb07fafaac84ef483affffda64d7d23edfee1e35955111d1147682c9be955ffdc21298acab5c5b297e7d8e590db6f7a45e4b574cbbf30287fb72eca1a791319a4fd9b9dd8e3dd180d9ad7bbefcc28ab181d65ee89902c71ddcabe414cbfec469e8c6e7b11a2888d858cab007de7df4cd209354468918cd9196663192dd46b732e31235c603c46b00175bae3f536003a21eba94080cf5598533d633b5ba4aceee3d935aff8c6b960ab1f1f21f490c2b7d886377ef1f63d171f4b595e4001ea94a332c292fd6adc7870803e60a0f8a9d50607a2d35acef61f285ebc72479c4d4f7b73487caebddc99c65072eca60ec01543722e6423b02ebb527fbd4392ab3f3a617c89917813fe0f13de5712f80026acec24f31162b61da0a2781bc2676ef17c0eb9571c8b83b5669f22041134dc6574447832ec580337852fbe60a707747e4d4120050805fec5b36aef8d51729da48518bb27750752e7f7636d582edc45bb7cc45c6875fb80da53cdefcc845c4de6d75f593d59d06657dad71e7190551a471130215458df3b789228ab6530a8ab03af0f807228bb454ad9426e0b9dba26abcde8c2ce080b3c708e702057587db6e3078f1053ada7cb26bf2cad2c3cd54df2045b575b0f7a8925689d0344bb4655937c35fb3cfa8204a704cf7c0c8d74bfe5ba6c9e15ec26e38e46d44ef37da3466b28469a79828a99f08a4b2acb5b53b6ac6eaae47ff32d31f25b94d88aeb042b477c63e0f3bd414dd7dec80c23b22fb7f68cfeee7f2cc8e9d7d2638055aabcc033d7b563111f7fc746990f1f9bcba5a2c02dfa6fda46c53e19b150f6d7811d32d464bd76be286a36025679e47ab8cc83d79e08cfe97058872adc80e9bfd4ecad14cc948125ea34778ee0660f22bd7f6b4cdfc18f61eca9987ee73a1dde815cbd79f3e9e8bdc7ae1a03460c72326690e3ab6d68892e80ef0b28e7d7d1051031bdc8aac92f4f17b8abe7485c0dd9c4543e9ad148d7884d4bfe630f7b15d084f375d3c2246ab48992d8b251eb12af12b0fd75e07bfe05bc483b3d3c521b12206f223b24d0513faf45656fd70c4e40a2d85b06c14e633807463d35440c6e6ff9c90782677f1de6f8099f2e97cf700d04add6f380b772ff656a372f8bfe91bc16b8151fdef80d3482f7752adcc9f82c10f582f261ccc647958b3a1b34226972dde904d9ea698c2faf61adab492e3bb492060e2c2af0102e77de5bbfcc2dd0da70c87046be6e089a1be8ecd532b60d9581fcc9a75a9f97361290d2db5d2e4e5d216e8aae0851d8e3c5914b034206b99acd3627c23cc0e726c3da152529c0d0aeb2516b0375096af1da6e3e6ef8baf4bdc5285bc84ae41c351716d0252f073f149fa1e00bf834d44fb62b55f240c4cc22200144cf1b443e55e65d53af7ca9efc873f6040d98c571e5c010d88e20b85b804afdb1d42dbe07853e9934ff798f0c8f26190d28e5b3c1598ebf63781b49f1b5f5b944ef56ffff52b6565c5b96667ac49cc9536d1e7513024328350033b9a8a102aaaa49e9ecd0d0c142dc42c8faaab741240dddf76b02071c58deb5704324a5febe3709b9a87a3bd388d4376ece76ec4fa996f07618fecbb57e1a55c9cc6e5a63143d323003e935243c49552f83975569a59306521a267d826b1abc22f0db3b5db89a367f69c17053e309758a791a147408705182587226df276e11aeb6979114d6e6ea61bb45f68209215ffdc5a8c9d6fb7e775600e3710f3dd532a195a893a86a9324e7e1f5f2bf5bfe9383d6857a3243cbd1b8f726af46ab93ad06fba88b192ad46a15068027dc42131b0f482d146387b0b261a54664c81d41587a196963b55526d56e7317eff6f9859a9f580330bc37ba95be2bc8eabc45a50fe63929bd8b37f7ed3f4cb072272f50f61a66c2b25d676ecfc200a67b015a7255554d8633ec9a0025e249a4c746167c2a1060cc09d6bd69057cde004e8eafbfc6bd4574992ece5a5f6d03b9eaee48a75c72da57395e169e26041d6ed3b65b9c306254b06b09f394fda392e26d911e2f1ced495a2347e9c68138d96e1d84fb26f7e284626fcf756fbc9a4575305555b099f6832a2193c9eb6b5abb95fab25703852be6ff25ec40bbe0c8bfd118aa38f0e9554e00ba3bc7eef0213060d25b23cd6c32e5ff461d82124b519220b115b6f2f18cd3371cd837ced26b69814f0f09027cf1338dc424e9da44d1ffd5c3e0625bb2b8936d36f9430345af3e119f92994899174a0df8c0e4aefb3dd69119b7b957902caf98b1174df0e3b6e7eaf365178511f0ed1b31157730a389c558dfb71105d985c5ddf6e60588431d8adff58f0b5b6fb92ec73b16a6abafe862001f559c85850cffa583c07f0bb766af7d1a11d91bd1c51d4b2e760703b0868df98c4c79093782d7caef607b330a44e31281a812a80dd1ca1df8232a7eb9c7b12decc2ad8c1273051620fee9ba58de4b2879394a701880f75a372f50f25afaa95c4bd2318007851e1c7b04898446c8e792c9f467f169978fe22b4ff6d7f86573631ebf795e5c1ab8fe85b76022ae4b1ed6a5efc02ecfae8b8c96875a101670ec783394b3388b6bb2e49d93f35570fea9f66cb5aa13bf7c211ad307df3f270a4de667759673c4c0c8c70a740abbbf866d3ce9758c92732e8316cab0fd7b44083adda52db9206455dc03020d62863541165a35cc77dec1ff2f610d35d41e16841d87a4f2cb1a8b0e9f048c2c69649052bc798e91b8f7b1650707ebf7fd0b24509ce0e83c5d622bd0d4427262cd09752c22f3156e400fb256402f06603d1ca839ee8754f408603c21b35dffafa3ef07270f1014352be11744d77e1c365110e52cd516ec3d7258cb23037f35f963bf2eeee1ed77caaa2618444fdc739b0624540ceb791d912d077de3386641f2a1463aee3c73f61457b2d51ff1e18d5256da064a7cb04fd1682a48d26f6dc4be147e682957815d1e1c31ab208f79c254681bd008b01d9bbfd6df63fbd59a03dba903d39cb51dec5a38fd27e740310d70cfd2cd4d0839ef24e27725293f2af1d2b728dcda6fc444e3e35145c4cac1affce73b7b99181881ecbad24e47775d475fbb4869e216782ada651ce95af7ea1820f71baf1956f4cc4a487e33e1b284077e4a30509cd068d13b0aa146532ce8e10feb52e71bf2bf0476d99b634d198a1b85c4a7b8001a39d05ed4413ad53c1fc242e58a834d8d2c2c537ad6ba9d6b7e87373568b42cc3b8df4717812092c6f5ea91dbd72b59c827623bafe3999ca7fec5f1c4af8b66b305c9b138d6d79af07d0c780a27dad35ef50a711fc23a1bb70567a6754f3253090147984215275787afd2bb2c12787942e7dc7ec996f90be2173d3984206a6594899c181464fad9b78b718fdbca1ff0db5bf9720c1fceea2ebd62f0b81d943e2986eb204b6d7c64a0502c9f60458c349a1da820c25ff4341a72fea8f66251ee97f8f5721a4e691465f8f24c8454f7aa05a1f339581ca88fee21f5b27874a662eba05b2a28a8d10d17a1d8b5eb8d62386b74d8e87557137272619fbd3520c47ffb0371b04a88e548edf1e85657e912b658ecacdfc63cf007c2e3636575514ce402ea217756bc74d2f1fd8f57824d7718b7b80a27aa5bd9dd9f6375a28e009794cc8ea671e01e3c76a190f86d0647b941e779da687d1a47cefa9c52e85e4d715107e1c4e42ad65a834b403245dee643c2f7b0c355bc2aabc3e5502f6c3395899df540ff194bb0f614441b1104776e549634f217912aaf56fe539cf52436be520e49c6413af7be5f2bc567ce0b0030888491aaadcf5048e4be5534318b63ca18d24ae22ea8b84c534bb16b5e89be9a97df5f26bf9c196cbda125380ace6283f5ca1138096adc4cbfabef87ec0a214e489765302f5ba8d22d175f4c44a60f071c4a4cd70c72df3d3b679b80e8adb29f506a352b95f4a047cade72c49c8cf57f7256fc4bd2a80a76ce25bb2f69c56ef539a6fbfa5771f5b524d7c9668b9bdcf36b42f4972262f9620fd16623dcd7a01163972135544e28c7d7b3ba773eb4fc19a9f356147e87ceef0fae8239cd9af066e786b7e36f207bac0c99ca40c3fa8d174506bde6daada87881bab469fba3f374ce4d28a88b93c40275b4313f58a042bbd3661d67562b97fa0de72ddd9d3489b02508854e4496caffce26df866a25ec7e13e2402bb690d973ba0b0ace987a979de8e3c2b897018962203ffbe2cec697960adac97aa6d5789062eee3d39cba18c42c1aa6af4f22b20f1dddc734f611324debe43d44d2c349e45f16323ef62133aec203d3f3315f98377002665086077e31e210b49ac5a263cc58e55dffe61dcb46fde9b3254309d314e9aa8cdb7a578c46a797521760d51a565ca0d45d6dced98e7d215d1373d135088f434f9732b3a606548b4bbd6356c3cd6aa3d7bd785e3983016a4d81ad153813d24010ba8672d8060f538b759ec30bd1cad9e82fdd7da0a8b381603e9325978c0a466d1aadb59a29d3c71b1bcd1a9b3b0bedb29c3364e0e8ef26b85484fa43f6a37a3215fe6e3c12207cc8bb9c94b96e92b260e33e91cf90f21fb31083632b316424b7b19f2f5213fbca06f53b5091c3173b5fc94c1045e2e73f57ead0fcdb4458a35fdce2c0575225955d2f5939981731d22b33cff03fe767a013da0b22388ccf168a134b3a353513b7c2a6c4b529761a2838fddf68dfbd0a1abe473eace950cac266671f7857955fb84121e0a505a51f024bc94007a21354cdb48e884a4960c1ad204b6b55eaf941fc57fbfed7aa8af71fa142e9fb1746deacdaf0ef81a13e51d98525673b977ad737ad4fba87b7c3af16be2ca81a6b0b73040259380e99939bbf1074c47adf2990204d39101cf9449a7c29f4e21c583b7c40eca3aa0d3cb7e9f5566cb2114a70630df071375d7966eb0b79483698a170b21881c775ba624b80b668f70d714a6d87a0a051f7679852db65fb78ea5df2b5787cec29244eaaf1528b08d65169d6b9699a5598e76d9eb0390863c9ff2b96ea6991c7448c66a651474086a04d9f28b7a72e8bfb35a7eb575c1b9771d21863eaee37c14975c8826ab99b6d4d8a11ea511b60740dddcc6bd8a49b252814ad7512375cd966aed0ba3478a7ae1b3b3ffb0ca843f05160354c7c2afd4ac2ffd164f9b80c60ef761af30a2f379582d4cc9f94bd2df255983378295d436d0eb2bf3739f38eaa1577f9061662825c51cc09bf576b71ba4975b9a4a66ea37205ecb930f83327238518757ab2dfc9d25b63be8abf4d67657d5d98f9bdd7799183f9679443873a1a99160e5f1f66d2257c90baa19505fa70cec3335943bcb3dcca3028f9b34aef83f5e4355fef3790df44b4763aa7ddb5cbba7c04b08edf545e38316663b838302d412cbafb0fa14d633a3dabf53ffbcebf4f08844d5d8c333bff147af758fe9ceab7cfaeccf1fbe95cb6d96465a0bf8d6aa80cb96992fc7545f0b1098c426ddb2fed5ac2975ec6045e44b4025bc9d6c8a4a861758b92f30e5fb57f00dbe89dc7a5c6e0cd4b18ad48df4b359c814d1d7b9aa1b46cec8731ee5b519059934190fa2f7251db9d013dc3318c20aefbb428c6945360d32a598265e95d4512377c38d985bcd1b1ed0dc6a4e82173218eed37e922bfbbf00d9d5eea08abc367903b57fda42539fe2b6abca9670b23e3ce2866d7a0f0bd916551b93a0ab8c96b9a3cbe87a17fe600d691a9bd3e2d587efaedc2820060461a8b2dc3a1a178f0f7056503991b02e3e3ca5d98063d203dcc507faf5d902789acd973464bcf39e57907253c5cf18325d33a1e4b7b52c566aad61b2dd133368b1d892e904d012653fcc3bb7f8217b6cb912271a904764cc049f66a7ca75076ad6e88d7069ed7afd58e74fab8afc8eb34ada73e99d1f6657064e1396d91d7aa190e06502631f738a095baa076ba395dc989f9134b9b2cf562b344e1af1de8990c117e5423a93fbf2c6e18220fd5af039b5c40f87c05b969290d582e602e98abd58ee80e152f74c3094378722c31453e60a9167b2a6c10beba701d623d3f83fa4e77de477ee8dff968977c281f7df560e7d0cabc8ce1df034667d86b8613e8dc26268726ed726618f84e95aa27717d0a15f1c1aa21e7f7a19622df62fe68c8f539ccd858288250c23695bac0d7c97e4f4994cf2aa929edc0b13315f047ad463709dd2679023d79b06ae0deded9888c0a2a56389086c44ced7872fef9d7b6032f79be609d5009f94c89f35a31497d781aceacf77de80108cd70b72cdd70a0a96e03cb48bf429d7b8605e0cbb5e4af9ca117c509bd366ed7c6fe1244571acb410bc6f8d176426abcc73de789285187e0522a17a80aee5a7ec1f0e3ab1f7fde3e66e014b42f28e6590a56fb4d6162aa9e395ec4cf2cf54b4fa779674edc7ea49d6e837a783ea8488ff03f5d603490d1558393bcdfdfca159ea1c207885f2fa5fda4f16587238b18c45e2d83dfaa028ca2d67f0b7acb1c9935fc2301f7f4ba9bcbc06b9af3a326f611e1e9e6d93c93c11758c8092681d371bd85f25f00dcc46c1015d15d0911fa9f4b4db06e604e070bc64fb6169caf17a4844e39d3ca4ccd0efa930f91617d14bc64b2c915ab7d158bfd1a3edf99562af377bb50f371b38c6feac8424e8a034d1471d92a188478a7e41ef947052a0f2c1685a5ec2b1a66c08e5eb9d163d8e7201400a98a0ffd38ba2c917f07bb114ee0250eb2524f09abbcde8d7855bfcf44cf6430236bcb265571f1455e03c29909c9faf61bbc181120b72574627262e70792cc8149c015b475bfb19a6865aa98127ad20ce29306d624b5f1f9bf26ded991f6659a40f2f5d17b46514efb11f90afa868b03bf498392453f2e2bce86727f5eb77124e05ca41704640d5429f1d4aa3ef19661a8ad650e34f177ece60c059080d4d8149c39ab686569ce2aaff7943d992730a830f7584578fdbd3ebc98401a137e6cdeefe363838b3a2a56ea2ca66bdff94a20ef39affb210329181b356beb70545520cd5d9b4b6fcbb2407f97252acea3ed87f4218266291b9238c2a4eeda12f7ae2ef634e104c769d998216ca7392c91a65f7559e0108a636fbdc33a8eab7b545e4ff3da4a6f32fdb804f5c4c431ba0ed780d5214bc68399232a83774582743c696b89cc0ebd110ee1cb72fbf85991e0c2bd055801ae4d9484ec3c94ccf8c3f85190e64826fe955b55e4b04efe3e4cf406c0bea84c992a18af6d3640e88ab34ec92e69f4b51b7a715d2212dd768a019690f655d68d19a0805a7a53939124ee6f5b5e48b7de6bc3f9098fdb5facab6f973b5a1477c397aefe691c2099efb4fbdfbe99509f43c2f3f8452dfe1f63df92e7a0dbeecad2f2ee6012ccf33a627b33c7e2b70aae4bb7bef47dc6935ca79b085fb3094773b2367eb3b0e8d95c5a8c987fbc72d15170a3f966cd6308729a4a6e032033c781680641a0accab1e2682f7e0c19bbc3831d1b97efa0fba00b8bb99ece27370f16a6b4bd3926d4f98017d8b7a23584b34964dcc7602b368d82d2555a346b96677addc77573bed662d7862b576e7334a6223b6f36e141d06bf658bb5e47f405760322b46d37f63955bea7555f6065ac17a580d2eda371309d48759aa462bfd4067aac6730ea6391a9bdb0aaf00d7a5311c5e52a32259dc49466b2e5945f063ba34388c1b15b6900e8c1d8d6c90bb3b4e64e596024919bd4b331eb98fdf08e22b31dd59f9a791ef24c276fe1561a07f89666bee2ebc9916e94475150f9bc3e240db6a803f1ae34ad8efa474b9ffc8178a68e0ab05192f2b7a73389d47088c4a450b85838997a1404afec5cfcf9ad604a49203d1581048d1d8fa1d55a74c0da87171a6e1ed2f0f9f112460a7117a6aa267f4015f3406ff9cc475197d879e0301de7b2abe50b0cbf6cf55d3548f6104705be4b5216784db2effcd539a7956498ba4a2bcde46eaf08cc8baa5316d993b54599bd3b79201880e233c1473b196abc3d15da0b9cf5e51a82052bbf09af7c0e02290ebc360b63e713102ace0446810e80936f234af849dd6d5783cceaffbcc7e493d695c943787b51ff33a7d9ccbd2008ba86035673c8e8670d543ff3b2ba40387de9d7bc0419ebfa88e34058fdf39cf650c8a291446da83f976ee9bfbbe48385601dd0bcb5f2d85834fabe0fc0957338b04576ddd9d1c2fb8e65a36968d7c0e80d797b096603ab4436c3e980553c94808b4dc74e2e66afe93786afa9f2b7e521fae7730084b6ab8777fbfe6b7ba34a0504806f44ce87d02b9abe856a24baac924e6b1e9b0e4f666dfa8aee90d07135503bf628a3a8578b702673f98a8a81cd7833ccff398d692363c82a845516efd2ae4b9a74b72dd0ee69950113c59e61b31203d618882d73a7eba59f932a7b2aadcc971b743a65daed8b0c8d61d146358220844e4eb32302fe5ea871259374c57bb0f62195918a954ea74519530a6e960f38cfc57fe7dc575dc33697fef0ae3173bf23f359dab53fb25741ad295f2ced8924fb1902894e94e195920ea5596e49e05b3783abc3b946faae16c8ba8b3f9b1aa7aeebade70a9fd0b52ead76f176f355d7de239f77e63b038526144e1b49f6299c89fa3e18db1b3b0fbcccc40d0028c043e9783524c4b85fc6338fae6973f5293a55d9c118339777be91bfaa3932eae0f8d7525109a19bab187ca814a484ffce65f413a8ea22ea627f6ecc03a149f9254d45f9d5956e2083493e6f8aa874aeff7c6429d1a18335175c294377694438d3037b96e4aab9454f7dffef76b5813d31a5f377dddcc01e1ec860b88b5b67be6abb889d82da155739dd4860339d33e7ed7d2aa309646bef3390f43f8e1b8ee75468f9c89c8b798febe1acdd493858c3121e9d1e0c4887d9eccc200b7b6492656fd6e22786b6adbf49a0e11456da10afb1d3e896d10ff2c637c0add4e44b9d0156f599b4495ead0c91574cba37c422e5b67d3857e9b035c232ffe1173a387544f1d3735193e00d52bcd0a08402691955c0ec3576209bdb30d4b3dab09d2cf1731e9f36820ffafe6f1e958239fe606a4adde758c5a2fabd59f2a143aa9ff8e5f9b4b8e06eff7750c4d3b2e9f785f332ee74db963c0aad8565fb8f43852a2bba1c04c401f6ab2cbd33beef28da3d399ee4ef17bc8ec2edfb5a6d666e70a6038b6c92c3501c901b1e56510d9059d2f94b7c3e098f9237f62839dcea1dfd1df8daa3919321cdf69efa80b3c2c1b106dbf0bd644323911b0ecfacada1cb3ced99dc03a21781699af040c49cd45dd6292840951e0171922275a557720613e73638a7f0867090293a965081048cb13d17b76f5136ce638c70646157ee7e447a33ca6019d0d778f773ac2d14df176dd1f497cb0e8b7a97e4f71da1874db722b19dec913732aebac806c797798cbe1feec74a86c2f538e8125407db0b2e6edfd2f1b02d05c43e508641338204e633f278a92d1e4baa33db9b892d0c42e509ffba299949cfeb39d47220e65c0b47505d2639c92fa91afaaa31a11bc5d31db74782e1595ceed4b699e259df053642cb27feae1a5a6883c54ca9b5efbe8b802f94a14343ef10a1040649e29b9b886475942b32c57f68e7434d8756641d3d5b101dd36e09483e93bfcb4f25fc7c515779489b8c0a000a9980f21a50dd14c9b2c5d8c396dbde7a69d6d20e95f114996bbab845ac2944f9a81fc5ac476cbccda30e85acfc5c04b84f566b47dac340206744e800a7f4f54c4a7ff3b2f9af933d57ce277b334ad22f686d5603632bb7e2f08a8258ae75eff36b0d97f3d3613ff39f8730936513b8cd07542da0763942b20e66cc32fbf91600cdf92e7fc5255a6adbc1a3bfb6707d19a4c9f61261ce12387ec59d44ea032d10a282f038aa4907eb6fe8f317a89ae74ea6c1489dc3afa1d7d770e1d57d3db0a154ae981469129646f31821e1dd4cdd32d9bbb53044a9a84a52a97cccd41ac38d56075472104c6041a0776fcb067037f3a9117a7ad4c0e08210a35540aab1fe1c3d27535b8d0453ecbc2467a67d9b70b1a8006b7968a776532b04e6f688082651ad296d0b302c7908fdefe09320a67be5775025929120a509dc7dec726c8a0e82aa664a40972ade66cef98ada9cd14c77a11ff055d136c7fe89d3df498973dd5464586c80eb0e53e0e48370eef6faef20dcc95ae3b449920005194bc928290b0bacfc49e12a676f1f23c4cc1bc33dc6cbd86358fa9a30aa89eb2483c3cd6b83cca79891d0160de91d4ce57d5904007ef581d439586c80bbf1ae709f57f55db82553ae0bc18e6d47c2fcae7afd536b90ff52675d0133120dd85612fd7555cbc558343ea08806b1bcf3b7787f2c613080c4e2841489bfb180deb1b60cbc8119699b036dc0f1194c1a4070e8b91d30b7c47ec61e0bb6da86eb29c3ec1ad236aa1232a6c9abd2a1cc47c82b75c9f54b2b8956e9ba3aa11f82c98c1465d2108d0ceb71f527047a1a8160b84aa5fd28eb6f4f477964c3361cc1a20f5f9d0b66b5a8ced1f1fa37f868c513e6da1abe9fff7fe66434276703f6cc0612af0bf5f60f248735019c3140f05281e269d7f002ea6928ec0e8c18eb725b5351134a9ae9f7a6b067b2308a48145576b9019586725c23a80cbc830800c9ad1b9232f6ca0358eaeb361ffff7846fd261068ad6baed747b3dc550b416835fe3ce67ddfc698ef683804c227cb2302f6d82e85c5512f88539404f613a0ff0d438354ef7e52a28a36b98f66a805dd74484d6f3f73f0dc28edf76f3a7430a6130315154cf2550d953ca377bd83fc5df978058357fc6b714a52bf116c630b485916cfecc2b9bbf1b5ab4ccf26da8d1fa2a115ce51e09ae1c07596027f971273d977d42a8bce76daa6649e31da51709cb1cc5bdf9f7a8d25904f8f384531cd881e57b93cfee106e48f53946be9de00526872b46a40ec0abe3a6992b4f52c12643dcf8c0f4d4185eddad2f9d257eed1f49c18340871ff32de637892c5fa825e1227edad6f21dc5f808e08ffb44ac4e275f100925456630effb7e03f091cc7860c9698abd34b56171541edb31bb515a34b84a8d89ea0fbfbe7b2b8c88ddc963f8fa39da45aa99f3aa5693210f20cd848808dcbced3f730f0336b338456233bf5ec5b21df1a2a09f2379a8595ea637fcba01c7f6b765e330554e1966ab7219d004e855df754f5f0f1df247b8e9be7a1aae56a3fea12b3c4f376625b3c1bd50acf0da503314c38bf2c6cef380265fb62879c94d97a552f24fa431ca2a44f6c9c9c4baa2ad1169d3e95c75b29ef3c2922609cd4e08d7f38c3f996f79ce3353a6b79291b3490983a6b54126935b683f1e85e384909f2611f7f127149251b84c741700dc09372ee75bd35cabe2f4d78613d190d84b950159e0136fde672b03a1a3819679202df50d2e72a780e18bd1941bdd9d5284e0f3ad5ed2bfb8fabe287ca2f17267ca7a91cd73f15d2f7b4b9e40a0642c9c03adf2b2d276a2fd0e17991e6f9de0f7258e2a47c69f2544cb02aa8248f320f5967fc5a27cfdd3e1ab7887f2cac10640e1c872d29d01118aa37ceff8b9c7ce4522338891f168bf5c0b5322e003c57d679d9b5f4328f69a05c8fae75e1c7d893a96d759285341473fda21d0e33df6e7e01fd7f8b8fee4b6a3f168bb18e97175f19dbcf56a70bd985612d8e545b6c006c80202e53a1a2742bec72b68c03b36e7a08e9fff36973cb7888cbddc139d3bcff7f9bfb24fabf5de213c293790a9f878e43df13a17dc5828188f51b750bb7373cb932d85da51f8b23b37258e1c2fdb2a823986fcd4149e0d90b8a81b8fd59029b28d27e207e0cf2d4597c1ad425ccc655809a5e6bb1d6345509ed6c8af83685cd76b20de12c3a8dd23f6fb30263553f86d481f91f3c1d43b596ddf7eda69f5897a8ce6b2d080a9380bbb5af7eb3285fcb23d28eafb7648fb2065da3e52c8dbd0fd2bb195e87c2ebeaf72183e521347c2d69ce72ca4bef390868bec18586fd0d77282a92d7ac9f75b3bf58944485a236632f7d22b93984eae51fcff4f452829ea085fcc3fed18399f67240a8028fc578f8fc99b3e896fb845dd593a493e9706a174d89c0136e51df4e04b5a04c4cfca4130a830264fc3f3b7519bb81ccebccccf3a50a666006b264db55c68efd0a03e3c821b4e0aceed5eaea23a70d14956dabb9596674f2caba60f70e50d2733d8c1da23c7c6508eb6e16058377a07abb5056220bc98597969e33ce10d12cbc07cbea15f0195849a22629163755f829fad8227edc54c0a10039680330e490803ad441b8195afdd1ee7f9915f0b6daf48e8d88f46697ea697857a209d8b2c36a8dd89537b9454f23cef2d20258c08cb519dcf557d163a938db68e7058b6c6251380e69da1e751640fa32c12351aa0fd67b7662a65a3ce96f18b417bd6730a57bedc6c020fb2d9f39b2476afca83e7ac3eef594bdbc842b12f2838effa939b2952371af51144b1fd836bb63594501869dccd34f516f26f5251a3b05172eab489da8b4102b69276cc72c4a35502bdf92ad5d857616cf4dc9f919af32c2885aa928b9a8f432316f80101611772def843dd4be19d7bdaf083599b2a9a792bda771f4f4f646d9504fd3c29f8564c616e8820c48bb41898fa309168dde2ca94a0d45c84f950e632cd658c04fde9fb4b8c5ad242713137a21ece27c0fe739c197268e6a6528a158ae88a7eafc34f8ae4fe0f7cd04ec2e33dfe7b042a965e0f05fe2e3ac30f9f33698912aff56edf5756ec081b01b2816cdf34169b6064e69486e87fa0cdc7ecf330a65334fc7d7f7bbf08164466d956b0cc62cfe798fb4d6bd3bc4a429d5eb1d196177aa2ae5f31ae21dd3e7cc524da63a556858c0ccf6b3e0616be091f585b318f4f0c2a8622d0d9684dda67c3d28808495e8efd62b1f0fdae157e961c6c5bee6ee63b90cc61f612088800418609c3b197b7409d7bcd8a53369b4a9bc962548ec50fd3b752c88c6ae41785545617b49da4052fe9ed173899f98271e065ea8cf4d70400128a08c99e153a78efd9a24075b531e71ad876854bb22c3108229a55704627927535b43cdf4a438f046fe1785811347acc2004a91e9c60aa87ed660228f145f29e65e0f774d674a6869262aa14ade1588c4be8f198bf8e7df619b0e4331a5931a2e8b1246bde1938685266c8d6c4913cd5c6d5a278587c789176dde4bcd4390246123c8eaf7230b954f15d7b3ad89df310271a52276afe7a875509432a7658e6b96206d93e5b28056df1f10c9c4a35f40c1131f30290e7798e61d197ca0ea29d9edfa23bd269cc68b022a0236e2bf6d49f288641edd012ba7bb40c130ed612154f0ff101d43a924d06f9199f55b9dbf5a834d251957537db3d7d817be1de33bff93a56d72c9b3fb6f8a9050ec425bcd7666dc4677e954295c61d47743991acee7e796bd682080daa5fa12e314287337674ea0c0394b1e3660d8a3aec378fc8e2e1a159bab309bc2e3dc4a32744c9bb7672d2cc8f193059797683c8614abd3f9f8be9d255fba4cb3fbcd5023a3ab1118590b6b93c65d2440fee25409e92a246622edac62103c7bfaaf22feff70e956d64528b7c4f91e84197524a77807e68bd0a3933a96b488f8f02e5220b6577dc672b9a8b7d6ddf90ff6b585bef46708062b14438a4f3e950239e533a6313fa39afd4952307c996e359629da872755c30fc16b39a6a94cfd862ca86fe13b979b0ac6735ece74be12072ac15941fe6b0337f0ccc2e57c38a764390141847b855015c8b02bfd97fe79ba4a90a58d5ee2a17a734772ce4131d9323b4d5ce1d8df2c339489d7f862320c62357ff37c1b09f627f6f116599b51905402812a45651aad8e420bfc1ca5c31d9046a48bde485f2d326f1c775904afa48790dbc0ad56e1062fdaf4c88dd82645ff648baa453deadbcc18be9f94a8539650df746d13a85db47d45c8268a7c1ccc7c3a4245fa8eebdfdc0b172dc360201002afa077fa07fa5543960a82f81d81417f8d7c3070c3bb5dab0128a47838f2c43ac7ea4bc75b73afbab9fa42ee0deb10b93aaea0059bc38468e3e2b511833e5ebb0062645048c6106044866ed52d331a21fd90e9d2918d1e2b9e60110c6d1dfed8cab1a7e913ac3c4bd681493d398a0fc64108f7971c30184b5b202e69750f1d53140c0809a974341550e5faef1392a266c18333a19e48eafc6252138c7bf610aa440efee6ada47e619a1be9b9e89dbef8df1aab0446daa2e7f3ac9ceeed93886be8b63f56295bd43bde11be741238fb5754ef749df2962088c089adcb47612f1cf5a868e4c0a0c2437ecb5759da41989899951f96261d31343dc131de60243f48384e06faa87baac8da66ac6323a104f3c1b9013f79d9712befaf860c639739de3ab7f6f1376dd99cb7f6c8aa42fb0d0f2dc586b708bf2b8af0e681350663125e913f7c8f2cf03d566acc35f09bf46680fbb699bdbc06d2af725cebcca87caba9553d5fde4248360dde795a78dad54241cce04425902deab8aa6de34fea7ec003a8b9e94a1c82eb83ff19cf2ae9a5ddf59d6f5e0e96ade83eb8a07072fe4b497b26c09843f98a89d10719a4899c886240f395a527055b3b6a8f208bba4cf495dd8b04c5c4f684331929d638400cb8b4927368e7a2365753cdd5f206545a022cb412ae27176214efaaecc0578b9dc9b87610aea8dbe799a94c6ea88bf5ab3945534addd3f63d76856a0360a1eb505abb4be88ef6b571e8a692453f7b3c6e6051d5cc27bf7715af743dd6b6067ec7fb3e13219833198286ea8315faa6f367a606d8148972617d044f9af75f9f62e7db95fcf329273a8d3a328047cf1d25686cf6a696f5127ec71cdc7d5e1ecb212d8fa94f38a7c84d5cb5730f0a4ff8f70b4f41996092cff2ddd991ab30e22ba1ac0144ca776facd476ca07cb50d9289a234e9faf84926e322d271368682f3a0d403c7c80a04c48788742fd29c567806640b7f1bd8d1dd961d92edd846aead2d9f4ad6c6363b35ed5e7f872c32194fa6ff03d3696f2bf78f055e4019146b144ed1ad63be7c3022dec556cd8d2f3a0bbfe725ae304de8affffa097e7f8e2a91bbe59eb6cdeaa4246cff640dcf9824768418535effe74534331242e689734fc393ff38a8f3e88b450112ef26eb58df6d45d4c677aed1e7cfe1e5a681bb5f72aeace6b762cc72408cb004ec049c1cf4a31701068a1c7058cd2f0e98df911627bd791a85817cc503906256240fe4f830ebcc290ce216dfe5b6331d3cc612098e39b821e314b37858a40d1268f31f23bdb75ea64a5bfe3cbbd9284ea4caa57bc27ed3501e2419aa407e5f7b7a5dc7c64566f4abeaffb54d094357eaab85314c953a520eede2f4bbf2784b3cee19c5420e2d5a6a8b86c313605f16731ab67db8c8310290332d36e5dbb4d9a186c89753aea1f88fd6eee5f8f85ad00a237d9dab8e46f3d9755160b4a2b64a325396396af758755659abfe1bd31878a207c3fd141977a92ca93d3b3b7b37e8b1aa2de5c286d8032d1eb578f003e528147bd13c716756ac447eab3a0f57f3039b6f9707d10c282d91bb25bb6699af986ef5ce64df7bd26af607e41f664dbc228c9f0d8cc9cac99400b16842adf4c97fc4393040b5e5a2d7ce2df540cd9776500002b33030000000000000000000000000000000000000000000000000000000000cbaba2b1bed66214c277413dd7a68c0df51163db42b7d8086855b2a1bed799a250306269e9ebb91cecd71fa65b83b169139aa2b1d51147d246507fc10ac3ad25b37e8b1aa2de5c286d8032d1eb578f003e528147bd13c716756ac447eab3a0f57f3039b6f9707d10c282d91bb25bb6699af986ef5ce64df7bd26af607e41f664dbc228c9f0d8cc9cac99400b16842adf4c97fc4393040b5e5a2d7ce2df540cd9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdffffffffffffffffffffffffffffff8c0b22e8d378c362545ccf089f83e37846b45fc95eb52e71c26d2c222946ed765cf77fc50441c0b4d3b26dbf606fcaf71310128438846a65747a0c9089992a64b86d042d6725135e885024e11cb32719d6fc7b7ba44fbd996ad0ea64ebcb12deab65660000000000aa65660000000000eb71070000000000fcb6c164773147a712fbb0bce05010b8791f55c5ca76eeb0c04aa3ca7dc27c05dfd9e9eac6a715f5d984380a32bbcbd84dbf32b6bb8ee7d497ccaece223091c0a5ff697cd91e966e92a4a306ad61f53fd0f9b771ff1c6848bc6e54764a2b8fdaf40000002c3393704b6e144d3ceee58489a90f69abea2bad6d20498cfdf820bfc425e317336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71ab03d246092331a558c79a7afec160d02cbe7f0e20eedd6b15ec02f832323738b96f116d0383f3e5fc6a0fc68cebbeaf844af59cdcb6ef985621348442d8940c690b9a9e9aa1c9db991c7721a92d351db4fac990faaa1c0f3d26919676230214a9f513e4e65acdba48ed60b2ebaef60716d3b025eb916bb8aed8e9b55caed5a3fc5dff2d308198c26642803f82ae75466dad7c4717314f236da25bce94ad383fa29f2329e126f5ae3d83049a637fa012da9a3d21d576c7c5d2307e7978f4f7426718071b73210ab7ff86bcbcf3707287197fe36b04d3dd08cd16a96beeb3d3fc5a8d48e9cba2b71444ee1c9a4ab39d5dcf304a503a1c0203b781fe0f6861dab609ffbacdfaf1fe7a891c4efcb752a1ff0d3ccc404a6617f7628052bd055c113e42b3a91ff6ce91fdef1ea7bb8f7a6b62e2d22a18e70a11eb0942e51afeff79fe97bf87a44445541fe95e29f384f46776924c417807d68b2ea4f0ed046c920127847e730a65ec948eec6f215c1d975187da20e23ed3baad7b480398b06a4dc3bf0dcfcab487e1d510d3b8a06fc949b9ffaedafc0b7ee56e0f13183e05d8fe176d56da0b98fbf1696d868e334a174cb15a8d20862e7f750b010000000080c3c901000000006e9b4601000000004ff492640000000038020000f87c8668050000000000000000000000000000000000000000000000000000009c4297f072de8d2dad3eaa129e0b68c9bbff1ce399714c4d8c604594f4b02b972e08e5688095baf5b9a28e5068c4228b0380b420a6ff0506f7030406a0c773d74dafac0384726cb1273b49d054eedf30829d1beeb951dc5a79ccf158d3834dde6275696c646572307836395f656600000000006b55060000000000ba22e236ac727bc8f4a7b0b5009eca1c4d5bd9064abd342ad7d0e8671e28084331822134cd1811991be820abdbae380725db94705ad88f06c92bd252aed1362f7ab3ce9a383c3e794755c770e9371a07fee31cbf619cf0572f97f8eeb45950ccf4000000066689db3e612aeab689f216211aac277766d546ef178df9595d19cac566ab64336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0edb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71940c9e2fcdf5b2feecc20339bc42a76f200f923f264f67ba033d7ea27924fb58b31977868960ddd34566cb0c99f7c8d226a372aefe4a2cd056640840cafde7e2690b9a9e9aa1c9db991c7721a92d351db4fac990ce8a4c49668ff3fe3a778fd373939b6ca28cd1436c7ac9a59b5ac562f3388f0779d8b41e8c68b8b75ee1463e8ba77879626a6b147eccaef5e12a8698c2a830388d63a3fd458a1948f41a6f83f05314b57874469a884fd3006bad001e7aa0b95bd9b7ff2ae741cb35d4f4b3334a9867b12727c1f5ff8e6956f2720a57f17d27283af4f6cdcf89893e490aea5c925a78bd86111d50dc56b91594507d49c97c89899a24e9f7122edd2de4e9ed36ef86bfcdfa792671e01ce4460253ecfe8a5b57577c10965cb0bc2f7995cf15687b967f24d833f0effb230e9afc2dc6e3c0db1320ceffe64769bd72ab5a10c1c7bd3dae608c6142d0a1b92b8e29e28ef72ae0d2cbed387e1b11411d58161824b8b0ff3a56711fc64f8f29b83cafb779ef8a93e63cddbeec6e9da7830d4e874cb008421e95b596b87661aab2e8ab6f3cb0fcf4fcf92bc75b4f36595710dae61ebe6763595994148bf06d1c641fa69cc4002d18b48136750b010000000080c3c90100000000b7a6b20100000000cbf09264000000003802000049f0f2cf040000000000000000000000000000000000000000000000000000000f5516795996b9f2310c2002b3b20619b9ac4536a4d4bce4641722056d64d0a5c0b9bc2b9c8c4b4c469be2e86d6eb609560dd56021fdeb22c377cf19956a3f08e1a663a4eecaf19ff6b472e8f71bf294308137816f998e4b7f95d4ff19590aa1406275696c64657230783639
diff --git a/testing/ethportal-peertest/src/lib.rs b/testing/ethportal-peertest/src/lib.rs
index 5c9d10d16..330f04636 100644
--- a/testing/ethportal-peertest/src/lib.rs
+++ b/testing/ethportal-peertest/src/lib.rs
@@ -19,7 +19,7 @@ use itertools::Itertools;
 use jsonrpsee::async_client::Client;
 use portalnet::constants::DEFAULT_DISCOVERY_PORT;
 use rpc::RpcServerHandle;
-use trin::cli::TrinConfig;
+use trin::{run_trin_from_trin_config, TrinConfig};
 
 pub struct PeertestNode {
     pub enr: Enr,
@@ -43,7 +43,7 @@ impl Peertest {
 
 async fn launch_node(trin_config: TrinConfig) -> anyhow::Result<PeertestNode> {
     let web3_ipc_path = trin_config.web3_ipc_path.clone();
-    let rpc_handle = trin::run_trin(trin_config).await.unwrap();
+    let trin_handle = run_trin_from_trin_config(trin_config).await.unwrap();
 
     // Short sleep to make sure all peertest nodes can connect
     thread::sleep(time::Duration::from_secs(2));
@@ -55,7 +55,7 @@ async fn launch_node(trin_config: TrinConfig) -> anyhow::Result<PeertestNode> {
     Ok(PeertestNode {
         enr: ipc_client.node_info().await.unwrap().enr,
         ipc_client,
-        rpc_handle,
+        rpc_handle: trin_handle.rpc_server_handle,
     })
 }
 
diff --git a/testing/ethportal-peertest/src/scenarios/bridge.rs b/testing/ethportal-peertest/src/scenarios/bridge.rs
deleted file mode 100644
index 9c864be97..000000000
--- a/testing/ethportal-peertest/src/scenarios/bridge.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-use std::{path::PathBuf, str::FromStr};
-
-use alloy::primitives::B256;
-use ethportal_api::{
-    jsonrpsee::http_client::HttpClient, types::network::Subnetwork, BeaconContentKey,
-    BeaconContentValue, ContentValue, RawContentValue,
-};
-use portal_bridge::{
-    api::consensus::ConsensusApi,
-    bridge::beacon::BeaconBridge,
-    census::Census,
-    cli::{BridgeConfig, BridgeId, DEFAULT_EXECUTABLE_PATH, DEFAULT_SUBNETWORK, ENR_OFFER_LIMIT},
-    constants::{DEFAULT_OFFER_LIMIT, DEFAULT_TOTAL_REQUEST_TIMEOUT},
-    types::mode::BridgeMode,
-    DEFAULT_BASE_CL_ENDPOINT, DEFAULT_BASE_EL_ENDPOINT, FALLBACK_BASE_CL_ENDPOINT,
-    FALLBACK_BASE_EL_ENDPOINT,
-};
-use portalnet::constants::{DEFAULT_DISCOVERY_PORT, DEFAULT_NETWORK, DEFAULT_WEB3_HTTP_PORT};
-use serde::Deserialize;
-use serde_json::Value;
-use tokio::time::{sleep, Duration};
-use trin_utils::cli::network_parser;
-use url::Url;
-
-use crate::{utils::wait_for_beacon_content, Peertest};
-
-pub async fn test_beacon_bridge(peertest: &Peertest, portal_client: &HttpClient) {
-    let mode = BridgeMode::Test("./../../test_assets/portalnet/beacon_bridge_data.yaml".into());
-    // Wait for bootnode to start
-    sleep(Duration::from_secs(1)).await;
-    // url doesn't matter, we're not making any requests
-    let client_url = Url::parse("http://www.null.com").unwrap();
-    let consensus_api = ConsensusApi::new(
-        client_url.clone(),
-        client_url,
-        DEFAULT_TOTAL_REQUEST_TIMEOUT,
-    )
-    .await
-    .unwrap();
-
-    let bridge_config = BridgeConfig {
-        executable_path: PathBuf::from(DEFAULT_EXECUTABLE_PATH),
-        mode: BridgeMode::Latest,
-        e2hs_range: None,
-        e2hs_randomize: false,
-        portal_subnetwork: Subnetwork::from_str(DEFAULT_SUBNETWORK)
-            .expect("Failed to parse default subnetwork"),
-        network: network_parser(DEFAULT_NETWORK).expect("Failed to parse default network"),
-        metrics_url: None,
-        client_metrics_url: None,
-        bootnodes: "default".to_owned(),
-        external_ip: None,
-        private_key: B256::random(),
-        el_provider: Url::parse(DEFAULT_BASE_EL_ENDPOINT)
-            .expect("Failed to parse default el provider"),
-        el_provider_fallback: Url::parse(FALLBACK_BASE_EL_ENDPOINT)
-            .expect("Failed to parse default el provider fallback"),
-        cl_provider: Url::parse(DEFAULT_BASE_CL_ENDPOINT)
-            .expect("Failed to parse default cl provider"),
-        cl_provider_fallback: Url::parse(FALLBACK_BASE_CL_ENDPOINT)
-            .expect("Failed to parse default cl provider fallback"),
-        base_discovery_port: DEFAULT_DISCOVERY_PORT,
-        base_rpc_port: DEFAULT_WEB3_HTTP_PORT,
-        offer_limit: DEFAULT_OFFER_LIMIT,
-        enr_offer_limit: ENR_OFFER_LIMIT,
-        request_timeout: DEFAULT_TOTAL_REQUEST_TIMEOUT,
-        bridge_id: BridgeId { id: 1, total: 1 },
-        data_dir: None,
-    };
-
-    let mut census = Census::new(portal_client.clone(), &bridge_config);
-    let census_handle = census.init([Subnetwork::Beacon]).await.unwrap();
-    let bridge = BeaconBridge::new(consensus_api, mode, portal_client.clone(), census);
-    bridge.launch().await;
-
-    let value = std::fs::read_to_string("./../../test_assets/portalnet/beacon_bridge_data.yaml")
-        .expect("cannot find test asset");
-    let value: Value = serde_yaml::from_str(&value).unwrap();
-    let content_key = BeaconContentKey::deserialize(&value[0]["content_key"]).unwrap();
-    let content_value = RawContentValue::deserialize(&value[0]["content_value"]).unwrap();
-    let content_value = BeaconContentValue::decode(&content_key, &content_value).unwrap();
-
-    // Check if the stored content value in bootnode's DB matches the offered
-    let received_content_value =
-        wait_for_beacon_content(&peertest.bootnode.ipc_client, content_key).await;
-    assert_eq!(
-        content_value, received_content_value,
-        "The received beacon content {received_content_value:?}, must match the expected {content_value:?}",
-    );
-    census_handle.abort();
-    drop(census_handle);
-}
diff --git a/testing/ethportal-peertest/src/scenarios/mod.rs b/testing/ethportal-peertest/src/scenarios/mod.rs
index 3bb245fc1..2e5efe0b9 100644
--- a/testing/ethportal-peertest/src/scenarios/mod.rs
+++ b/testing/ethportal-peertest/src/scenarios/mod.rs
@@ -1,5 +1,4 @@
 pub mod basic;
-pub mod bridge;
 pub mod eth_rpc;
 pub mod find;
 pub mod offer_accept;
diff --git a/testing/ethportal-peertest/src/scenarios/put_content.rs b/testing/ethportal-peertest/src/scenarios/put_content.rs
index 1711e6709..605c57b29 100644
--- a/testing/ethportal-peertest/src/scenarios/put_content.rs
+++ b/testing/ethportal-peertest/src/scenarios/put_content.rs
@@ -5,7 +5,7 @@ use ethportal_api::{
     Discv5ApiClient, HistoryNetworkApiClient,
 };
 use tracing::info;
-use trin::cli::TrinConfig;
+use trin::{run_trin_from_trin_config, TrinConfig};
 
 use crate::{
     utils::{
@@ -40,7 +40,7 @@ pub async fn test_put_content(peertest: &Peertest, target: &Client, network: Net
 
     // Spin up a fresh client, not connected to existing peertest
     let (fresh_ipc_path, trin_config) = fresh_node_config(network);
-    let _test_client_rpc_handle = trin::run_trin(trin_config).await.unwrap();
+    let _test_client_rpc_handle = run_trin_from_trin_config(trin_config).await.unwrap();
     let fresh_target = reth_ipc::client::IpcClientBuilder::default()
         .build(&fresh_ipc_path)
         .await
@@ -90,7 +90,7 @@ pub async fn test_gossip_dropped_with_offer(
 
     // Spin up a fresh client, not connected to existing peertest
     let (fresh_ipc_path, trin_config) = fresh_node_config(network);
-    let _test_client_rpc_handle = trin::run_trin(trin_config).await.unwrap();
+    let _test_client_rpc_handle = run_trin_from_trin_config(trin_config).await.unwrap();
     let fresh_target = reth_ipc::client::IpcClientBuilder::default()
         .build(&fresh_ipc_path)
         .await
@@ -259,7 +259,7 @@ pub async fn test_gossip_dropped_with_find_content(
 
     // Spin up a fresh client, not connected to existing peertest
     let (fresh_ipc_path, trin_config) = fresh_node_config(network);
-    let _test_client_rpc_handle = trin::run_trin(trin_config).await.unwrap();
+    let _test_client_rpc_handle = run_trin_from_trin_config(trin_config).await.unwrap();
     let fresh_target = reth_ipc::client::IpcClientBuilder::default()
         .build(&fresh_ipc_path)
         .await
diff --git a/testing/ethportal-peertest/tests/rpc_server.rs b/testing/ethportal-peertest/tests/rpc_server.rs
index 8a3dea376..6c026fedf 100644
--- a/testing/ethportal-peertest/tests/rpc_server.rs
+++ b/testing/ethportal-peertest/tests/rpc_server.rs
@@ -27,7 +27,7 @@ use serial_test::serial;
 use ssz::Decode;
 
 mod utils;
-use trin::cli::TrinConfig;
+use trin::{run_trin_from_trin_config, TrinConfig};
 use trin_utils::submodules::read_portal_spec_tests_file;
 use url::Url;
 use utils::init_tracing;
@@ -57,7 +57,8 @@ async fn setup_web3_server() -> (RpcServerHandle, DynProvider, Client) {
     ])
     .unwrap();
 
-    let web3_server = trin::run_trin(trin_config).await.unwrap();
+    let trin_handle = run_trin_from_trin_config(trin_config).await.unwrap();
+
     let ipc = IpcConnect::new(DEFAULT_WEB3_IPC_PATH.to_string());
     let web3_client = DynProvider::new(ProviderBuilder::new().connect_ipc(ipc).await.unwrap());
 
@@ -67,7 +68,7 @@ async fn setup_web3_server() -> (RpcServerHandle, DynProvider, Client) {
         .build(DEFAULT_WEB3_IPC_PATH)
         .await
         .unwrap();
-    (web3_server, web3_client, native_client)
+    (trin_handle.rpc_server_handle, web3_client, native_client)
 }
 
 #[tokio::test(flavor = "multi_thread")]
@@ -95,8 +96,7 @@ async fn test_batch_call() {
     ])
     .unwrap();
 
-    let web3_server = trin::run_trin(trin_config).await.unwrap();
-
+    let trin_handle = run_trin_from_trin_config(trin_config).await.unwrap();
     let url = Url::parse(DEFAULT_WEB3_HTTP_ADDRESS).unwrap();
     let client = ClientBuilder::default().http(url);
 
@@ -113,7 +113,7 @@ async fn test_batch_call() {
     client_version_future.await.unwrap();
     node_info_future.await.unwrap();
 
-    web3_server.stop().unwrap();
+    trin_handle.rpc_server_handle.stop().unwrap();
 }
 
 #[tokio::test(flavor = "multi_thread")]
diff --git a/testing/ethportal-peertest/tests/self_peertest.rs b/testing/ethportal-peertest/tests/self_peertest.rs
index 213f0e525..9896c327a 100644
--- a/testing/ethportal-peertest/tests/self_peertest.rs
+++ b/testing/ethportal-peertest/tests/self_peertest.rs
@@ -1,8 +1,5 @@
 #![cfg(unix)]
-use std::{
-    env,
-    net::{IpAddr, Ipv4Addr},
-};
+use std::net::{IpAddr, Ipv4Addr};
 
 use ethportal_api::{
     types::{
@@ -19,7 +16,7 @@ use portalnet::constants::{DEFAULT_WEB3_HTTP_ADDRESS, DEFAULT_WEB3_IPC_PATH};
 use rpc::RpcServerHandle;
 use serial_test::serial;
 use tokio::time::{sleep, Duration};
-use trin::cli::TrinConfig;
+use trin::{run_trin_from_trin_config, TrinConfig};
 use trin_utils::cli::network_parser;
 
 mod utils;
@@ -440,7 +437,7 @@ mod protocol_v1 {
 #[tokio::test(flavor = "multi_thread")]
 #[ignore = "test is flaky: fails in some environments and in CI sporadically. Re-add #[serial] when re-enabling"]
 async fn peertest_offer_concurrent_utp_transfer_limit() {
-    let (peertest, target, handle) = setup_peertest_bridge(&[Subnetwork::History]).await;
+    let (peertest, target, handle) = setup_peertest_http(&[Subnetwork::History]).await;
     peertest::scenarios::offer_accept::test_offer_concurrent_utp_transfer_limit(&peertest, target)
         .await;
     peertest.exit_all_nodes();
@@ -560,15 +557,15 @@ async fn setup_peertest(
     ])
     .unwrap();
 
-    let test_client_rpc_handle = trin::run_trin(trin_config).await.unwrap();
+    let test_client_rpc_handle = run_trin_from_trin_config(trin_config).await.unwrap();
     let target = reth_ipc::client::IpcClientBuilder::default()
         .build(DEFAULT_WEB3_IPC_PATH)
         .await
         .unwrap();
-    (peertest, target, test_client_rpc_handle)
+    (peertest, target, test_client_rpc_handle.rpc_server_handle)
 }
 
-async fn setup_peertest_bridge(
+async fn setup_peertest_http(
     subnetworks: &[Subnetwork],
 ) -> (Peertest, HttpClient, RpcServerHandle) {
     utils::init_tracing();
@@ -591,9 +588,6 @@ async fn setup_peertest_bridge(
         .map(|subnetwork| subnetwork.to_cli_arg())
         .join(",");
 
-    // add fake secrets for bridge activation
-    env::set_var("PANDAOPS_CLIENT_ID", "xxx");
-    env::set_var("PANDAOPS_CLIENT_SECRET", "xxx");
     // Run a client, to be tested
     let trin_config = TrinConfig::new_from([
         APP_NAME,
@@ -603,7 +597,6 @@ async fn setup_peertest_bridge(
         &subnetworks,
         "--external-address",
         external_addr.as_str(),
-        // Run bridge test with http, since bridge doesn't support ipc yet.
         "--web3-transport",
         "http",
         "--web3-http-address",
@@ -618,18 +611,9 @@ async fn setup_peertest_bridge(
     ])
     .unwrap();
 
-    let test_client_rpc_handle = trin::run_trin(trin_config).await.unwrap();
+    let test_client_rpc_handle = run_trin_from_trin_config(trin_config).await.unwrap();
     let target = ethportal_api::jsonrpsee::http_client::HttpClientBuilder::default()
         .build(DEFAULT_WEB3_HTTP_ADDRESS)
         .unwrap();
-    (peertest, target, test_client_rpc_handle)
-}
-
-#[tokio::test(flavor = "multi_thread")]
-#[serial]
-async fn peertest_beacon_bridge() {
-    let (peertest, target, handle) = setup_peertest_bridge(&[Subnetwork::Beacon]).await;
-    peertest::scenarios::bridge::test_beacon_bridge(&peertest, &target).await;
-    peertest.exit_all_nodes();
-    handle.stop().unwrap();
+    (peertest, target, test_client_rpc_handle.rpc_server_handle)
 }


Reviews:
user: login: morph-dev
body: I reviewed entire PR quickly and I don't want all this functionality in HeaderOracle.

Also, if I'm not mistaken, we are still converting requests/responses to/from JSON, right? What do you think about getting `Arc<OverlayProtocol<...>>` (e.g. `history_handler.network.overlay.clone()`) and using it directly? Or do you think that is value in using high level API?

---

I agree that current bridge peertest isn't testing much. But I believe that we should have some bridge peertests in place. I don't expect this to be done in this PR. I don't expect this to be done in the next PR because it isn't a priority. But I believe we should make a issue to track it so we don't completely forget about it.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-28T21:37:13Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T02:35:17Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T04:47:20Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T04:47:35Z
user: login: morph-dev
body: Looks much better.
Several suggestions, nothing too major.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-29T12:42:46Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T01:57:51Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T01:58:01Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T02:06:36Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T05:56:50Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T06:07:37Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T06:31:20Z
user: login: morph-dev
body: Almost there. Few small comment.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-30T12:23:41Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T18:44:16Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T18:52:14Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T18:56:30Z
user: login: morph-dev
body: LGTM :rocket: 
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-30T19:12:02Z
user: login: KolbyML
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T19:18:54Z

Review comments:
diff_hunk: @@ -54,6 +53,17 @@ trin-utils.workspace = true
 trin-validation.workspace = true
 url.workspace = true
 
+# Trin dependencies
path: bin/portal-bridge/Cargo.toml
user: login: morph-dev
body: nit: I would assume that this now becomes core feature of the bridge, so no need to split dependencies
created_at: 2025-04-28T20:49:22Z
author_association: COLLABORATOR
path: bin/portal-bridge/README.md
user: login: morph-dev
body: I think line 7 should be updated as well.
created_at: 2025-04-28T20:52:11Z
author_association: COLLABORATOR
path: crates/validation/src/oracle.rs
user: login: morph-dev
body: I really don't think that most of this functionality should be in structure called "HeaderOracle".

If you want, you can get `mpsc::UnboundedSender<HistoryJsonRpcRequest>` from the oracle and have it in a separate object that will let you send these requests.

created_at: 2025-04-28T21:20:50Z
author_association: COLLABORATOR
diff_hunk: @@ -1,60 +1,193 @@
-use ethportal_api::{types::network::Subnetwork, utils::bytes::hex_encode};
-use tokio::process::{Child, Command};
+use std::{str::FromStr, sync::Arc};
+
+use anyhow::anyhow;
+use ethportal_api::{
+    types::{distance::Distance, network::Subnetwork},
+    utils::bytes::hex_encode,
+    version::get_trin_version,
+};
+use portalnet::{
+    bootnodes::Bootnodes,
+    config::{PortalnetConfig, DISCV5_SESSION_CACHE_CAPACITY},
+    discovery::{Discovery, Discv5UdpSocket},
+    events::PortalnetEvents,
+    utils::db::configure_node_data_dir,
+};
+use tokio::sync::{mpsc, RwLock};
+use tracing::info;
+use tree_hash::TreeHash;
+use trin_beacon::initialize_beacon_network;
+use trin_history::initialize_history_network;
+use trin_state::initialize_state_network;
+use trin_storage::{config::StorageCapacityConfig, PortalStorageConfigFactory};
+use trin_utils::dir::setup_data_dir;
+use trin_validation::oracle::HeaderOracle;
+use utp_rs::socket::UtpSocket;
 
 use crate::cli::BridgeConfig;
 
-pub fn build_trin(bridge_config: &BridgeConfig) -> anyhow::Result<Child> {
-    if !bridge_config.executable_path.is_file() {
-        return Err(anyhow::anyhow!(
-            "Trin executable path is not a file: {:?}",
-            bridge_config.executable_path
-        ));
-    }
-    let rpc_port = bridge_config.base_rpc_port;
-    let udp_port = bridge_config.base_discovery_port;
-    let private_key = hex_encode(bridge_config.private_key);
-    let mut command = Command::new(bridge_config.executable_path.clone());
-
-    command
-        .kill_on_drop(true)
-        .args(["--ephemeral"])
-        .args(["--no-upnp"])
-        .args(["--mb", "0"])
-        .args(["--web3-transport", "http"])
-        .args(["--network", &bridge_config.network.network().to_string()])
-        .args(["--portal-subnetworks", &subnetworks_flag(bridge_config)])
-        .args(["--unsafe-private-key", &private_key])
-        .args(["--web3-http-address", &format!("http://0.0.0.0:{rpc_port}")])
-        .args(["--discovery-port", &format!("{udp_port}")])
-        .args(["--bootnodes", &bridge_config.bootnodes])
-        .args([
-            "--utp-transfer-limit",
-            &bridge_config.offer_limit.to_string(),
-        ]);
-    if let Some(ip) = bridge_config.external_ip.clone() {
-        command.args(["--external-address", &format!("{ip}:{udp_port}")]);
-    }
-    if let Some(client_metrics_url) = bridge_config.client_metrics_url {
-        let url: String = client_metrics_url.to_string();
-        command.args(["--enable-metrics-with-url", &url]);
-    }
-
-    Ok(command.spawn()?)
+const APP_NAME: &str = "portal-bridge";
+
+pub async fn run_trin(bridge_config: &BridgeConfig) -> anyhow::Result<Arc<RwLock<HeaderOracle>>> {
path: bin/portal-bridge/src/handle.rs
user: login: morph-dev
body: Isn't this very similar to `run_trin` in bin/trin/src/lib.rs ? Can we refactor that one and make it reusable?

created_at: 2025-04-28T21:26:01Z
author_association: COLLABORATOR
diff_hunk: @@ -54,6 +53,17 @@ trin-utils.workspace = true
 trin-validation.workspace = true
 url.workspace = true
 
+# Trin dependencies
path: bin/portal-bridge/Cargo.toml
user: login: KolbyML
body: Ok I moved Trin crates under `Trin dependencies`, and moved the generic ones above
created_at: 2025-04-29T02:35:17Z
author_association: MEMBER
path: crates/validation/src/oracle.rs
user: login: KolbyML
body: Removed it
created_at: 2025-04-29T04:47:20Z
author_association: MEMBER
diff_hunk: @@ -1,60 +1,193 @@
-use ethportal_api::{types::network::Subnetwork, utils::bytes::hex_encode};
-use tokio::process::{Child, Command};
+use std::{str::FromStr, sync::Arc};
+
+use anyhow::anyhow;
+use ethportal_api::{
+    types::{distance::Distance, network::Subnetwork},
+    utils::bytes::hex_encode,
+    version::get_trin_version,
+};
+use portalnet::{
+    bootnodes::Bootnodes,
+    config::{PortalnetConfig, DISCV5_SESSION_CACHE_CAPACITY},
+    discovery::{Discovery, Discv5UdpSocket},
+    events::PortalnetEvents,
+    utils::db::configure_node_data_dir,
+};
+use tokio::sync::{mpsc, RwLock};
+use tracing::info;
+use tree_hash::TreeHash;
+use trin_beacon::initialize_beacon_network;
+use trin_history::initialize_history_network;
+use trin_state::initialize_state_network;
+use trin_storage::{config::StorageCapacityConfig, PortalStorageConfigFactory};
+use trin_utils::dir::setup_data_dir;
+use trin_validation::oracle::HeaderOracle;
+use utp_rs::socket::UtpSocket;
 
 use crate::cli::BridgeConfig;
 
-pub fn build_trin(bridge_config: &BridgeConfig) -> anyhow::Result<Child> {
-    if !bridge_config.executable_path.is_file() {
-        return Err(anyhow::anyhow!(
-            "Trin executable path is not a file: {:?}",
-            bridge_config.executable_path
-        ));
-    }
-    let rpc_port = bridge_config.base_rpc_port;
-    let udp_port = bridge_config.base_discovery_port;
-    let private_key = hex_encode(bridge_config.private_key);
-    let mut command = Command::new(bridge_config.executable_path.clone());
-
-    command
-        .kill_on_drop(true)
-        .args(["--ephemeral"])
-        .args(["--no-upnp"])
-        .args(["--mb", "0"])
-        .args(["--web3-transport", "http"])
-        .args(["--network", &bridge_config.network.network().to_string()])
-        .args(["--portal-subnetworks", &subnetworks_flag(bridge_config)])
-        .args(["--unsafe-private-key", &private_key])
-        .args(["--web3-http-address", &format!("http://0.0.0.0:{rpc_port}")])
-        .args(["--discovery-port", &format!("{udp_port}")])
-        .args(["--bootnodes", &bridge_config.bootnodes])
-        .args([
-            "--utp-transfer-limit",
-            &bridge_config.offer_limit.to_string(),
-        ]);
-    if let Some(ip) = bridge_config.external_ip.clone() {
-        command.args(["--external-address", &format!("{ip}:{udp_port}")]);
-    }
-    if let Some(client_metrics_url) = bridge_config.client_metrics_url {
-        let url: String = client_metrics_url.to_string();
-        command.args(["--enable-metrics-with-url", &url]);
-    }
-
-    Ok(command.spawn()?)
+const APP_NAME: &str = "portal-bridge";
+
+pub async fn run_trin(bridge_config: &BridgeConfig) -> anyhow::Result<Arc<RwLock<HeaderOracle>>> {
path: bin/portal-bridge/src/handle.rs
user: login: KolbyML
body: Done
created_at: 2025-04-29T04:47:35Z
author_association: MEMBER
diff_hunk: @@ -54,6 +53,17 @@ trin-utils.workspace = true
 trin-validation.workspace = true
 url.workspace = true
 
+# Trin dependencies
path: bin/portal-bridge/Cargo.toml
user: login: morph-dev
body: Why not keep them together?

If you want to propose that crates from this repo should be separated from external crates, then we should do it for all crates, not just bridge (and that should definitely be separate PR). I personally don't see much value in doing this and don't think that we should do it, but I wouldn't oppose it.

Also, why is `utp-rs` here and `eth_trie` is not?
created_at: 2025-04-29T11:06:55Z
author_association: COLLABORATOR
diff_hunk: @@ -102,114 +71,70 @@ impl HeaderOracle {
         }
     }
 
-    pub async fn history_get_enr(
-        node_id: &NodeId,
-        history_jsonrpc_tx: mpsc::UnboundedSender<HistoryJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = HistoryEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = HistoryJsonRpcRequest { endpoint, resp };
-        history_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("History network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from History network")),
-        };
-
-        let enr: Enr = serde_json::from_value(enr_value)?;
-
-        Ok(enr)
-    }
-
-    pub async fn state_get_enr(
-        node_id: &NodeId,
-        state_jsonrpc_tx: mpsc::UnboundedSender<StateJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = StateEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = StateJsonRpcRequest { endpoint, resp };
-        state_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("State network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from State network")),
-        };
-
-        let enr: Enr = serde_json::from_value(enr_value)?;
-
-        Ok(enr)
-    }
-
-    pub async fn beacon_get_enr(
-        node_id: &NodeId,
-        beacon_jsonrpc_tx: mpsc::UnboundedSender<BeaconJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = BeaconEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        beacon_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
+    /// Returns the HeaderWithProof for the given block hash by performing a recursive find content
+    /// request.
+    pub async fn recursive_find_header_by_hash_with_proof(
+        &self,
+        block_hash: B256,
+    ) -> anyhow::Result<HeaderWithProof> {
+        let content_key = HistoryContentKey::new_block_header_by_hash(block_hash);
+        let endpoint = HistoryEndpoint::GetContent(content_key.clone());
+        let response = self.send_history_request(endpoint).await?;
 
-        let enr: Enr = serde_json::from_value(enr_value)?;
+        let GetContentInfo { content, .. } = serde_json::from_value(response)?;
+        let content: HistoryContentValue = HistoryContentValue::decode(&content_key, &content)?;
 
-        Ok(enr)
+        match content {
+            HistoryContentValue::BlockHeaderWithProof(content) => Ok(content),
+            _ => Err(anyhow!(
+                "Invalid HistoryContentValue received from HeaderWithProof lookup, expected BlockHeaderWithProof: {content:?}"
+            )),
+        }
     }
 
     /// Return latest finalized root of the beacon state.
     pub async fn get_finalized_state_root(&self) -> anyhow::Result<B256> {
         let endpoint = BeaconEndpoint::FinalizedStateRoot;
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        let tx = self.beacon_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let state_root = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-
-        let state_root: B256 = serde_json::from_value(state_root)?;
-
-        Ok(state_root)
+        let response = self.send_beacon_request(endpoint).await?;
+        Ok(serde_json::from_value(response)?)
     }
 
     /// Return latest finalized beacon header.
     pub async fn get_finalized_header(&self) -> anyhow::Result<BeaconBlockHeader> {
         let endpoint = BeaconEndpoint::FinalizedHeader;
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        let tx = self.beacon_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let header = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-
-        let header: BeaconBlockHeader = serde_json::from_value(header)?;
-
-        Ok(header)
+        let response = self.send_beacon_request(endpoint).await?;
+        Ok(serde_json::from_value(response)?)
     }
 
     /// Return current light client store
     pub async fn get_light_client_store(&self) -> anyhow::Result<LightClientStore> {
         let endpoint = BeaconEndpoint::LightClientStore;
+        let response = self.send_beacon_request(endpoint).await?;
+        Ok(serde_json::from_value(response)?)
+    }
+
+    async fn send_history_request(&self, endpoint: HistoryEndpoint) -> anyhow::Result<Value> {
+        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
+        let request = HistoryJsonRpcRequest { endpoint, resp };
+        let tx = self.history_jsonrpc_tx()?;
+        tx.send(request)?;
+
+        Ok(match resp_rx.recv().await {
+            Some(val) => val.map_err(|err| anyhow!("History network request error: {err:?}"))?,
+            None => return Err(anyhow!("No response from History network")),
+        })
path: crates/validation/src/oracle.rs
user: login: morph-dev
body: You can make this even nicer with generics (and avoid deserializing return value everywhere). With it, most of the functions above become one-liners:

```rust
async fn send_history_request<T: Deserialize>(&self, endpoint: HistoryEndpoint) -> anyhow::Result<T> {
    // ...
    match resp_rx.recv().await {
        Some(Ok(response)) => Ok(serde_json::from_value(response)?),
        Some(Err(err)) => bail!("History network request error: {err:?}"))
        None => bail!("No response from History network"),
    }
}
```

Same below for beacon
created_at: 2025-04-29T11:18:26Z
author_association: COLLABORATOR
diff_hunk: @@ -55,14 +50,36 @@ pub async fn run_trin(
     )?;
 
     let portalnet_config = trin_config.to_portalnet_config(private_key);
+    let node_runtime_config = trin_config.to_node_runtime_config(node_data_dir);
+    let rpc_config = RpcConfig::from(&trin_config);
+    run_trin(portalnet_config, node_runtime_config, Some(rpc_config)).await
+}
+
+pub async fn run_trin(
path: bin/trin/src/lib.rs
user: login: morph-dev
body: Can you add the documentation, explaining how this is/could be used. Especially regarding return value.
created_at: 2025-04-29T11:48:01Z
author_association: COLLABORATOR
diff_hunk: @@ -190,5 +229,50 @@ pub async fn run_trin(
         tokio::spawn(network);
     }
 
-    Ok(rpc_handle)
+    Ok(trin_handle)
+}
+
+#[derive(Default)]
+pub struct TrinHandle {
+    pub rpc_server_handle: Option<RpcServerHandle>,
+    pub subnetwork_overlays: SubnetworkOverlays,
+}
+
+#[derive(Default, Clone)]
+pub struct SubnetworkOverlays {
+    pub history: Option<Arc<HistoryNetwork>>,
+    pub state: Option<Arc<StateNetwork>>,
+    pub beacon: Option<Arc<BeaconNetwork>>,
+}
+
+impl SubnetworkOverlays {
+    pub fn history_overlay(&self) -> anyhow::Result<Arc<HistoryNetwork>> {
+        match &self.history {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("History network is not available"),
+        }
+    }
+
+    pub fn state_overlay(&self) -> anyhow::Result<Arc<StateNetwork>> {
+        match &self.state {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("State network is not available"),
+        }
+    }
+
+    pub fn beacon_overlay(&self) -> anyhow::Result<Arc<BeaconNetwork>> {
+        match &self.beacon {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("Beacon network is not available"),
+        }
+    }
+}
+
+pub struct NodeRuntimeConfig {
+    pub portal_subnetworks: Arc<Vec<Subnetwork>>,
+    pub network_spec: Arc<NetworkSpec>,
+    pub max_radius: Distance,
+    pub enable_metrics_with_url: Option<SocketAddr>,
+    pub storage_capacity_config: StorageCapacityConfig,
+    pub node_data_dir: PathBuf,
path: bin/trin/src/lib.rs
user: login: morph-dev
body: I would move this at the beginning of file.
created_at: 2025-04-29T11:49:03Z
author_association: COLLABORATOR
diff_hunk: @@ -190,5 +229,50 @@ pub async fn run_trin(
         tokio::spawn(network);
     }
 
-    Ok(rpc_handle)
+    Ok(trin_handle)
+}
+
+#[derive(Default)]
+pub struct TrinHandle {
+    pub rpc_server_handle: Option<RpcServerHandle>,
+    pub subnetwork_overlays: SubnetworkOverlays,
+}
+
+#[derive(Default, Clone)]
+pub struct SubnetworkOverlays {
+    pub history: Option<Arc<HistoryNetwork>>,
+    pub state: Option<Arc<StateNetwork>>,
+    pub beacon: Option<Arc<BeaconNetwork>>,
+}
+
+impl SubnetworkOverlays {
+    pub fn history_overlay(&self) -> anyhow::Result<Arc<HistoryNetwork>> {
+        match &self.history {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("History network is not available"),
+        }
+    }
+
+    pub fn state_overlay(&self) -> anyhow::Result<Arc<StateNetwork>> {
+        match &self.state {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("State network is not available"),
+        }
+    }
+
+    pub fn beacon_overlay(&self) -> anyhow::Result<Arc<BeaconNetwork>> {
+        match &self.beacon {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("Beacon network is not available"),
+        }
+    }
+}
path: bin/trin/src/lib.rs
user: login: morph-dev
body: I would move this into separate file (e.g. handle.rs)
created_at: 2025-04-29T11:49:35Z
author_association: COLLABORATOR
diff_hunk: @@ -3,42 +3,37 @@
 
 pub mod cli;
 
-use std::sync::Arc;
+use std::{net::SocketAddr, path::PathBuf, sync::Arc};
 
+use anyhow::bail;
 use cli::TrinConfig;
 use ethportal_api::{
-    types::{distance::Distance, network::Subnetwork},
+    types::{distance::Distance, network::Subnetwork, network_spec::NetworkSpec},
     utils::bytes::hex_encode,
     version::get_trin_version,
 };
 use portalnet::{
+    config::PortalnetConfig,
     discovery::{Discovery, Discv5UdpSocket},
     events::PortalnetEvents,
     utils::db::{configure_node_data_dir, configure_trin_data_dir},
 };
-use rpc::{launch_jsonrpc_server, RpcServerHandle};
+use rpc::{config::RpcConfig, launch_jsonrpc_server, RpcServerHandle};
 use tokio::sync::{mpsc, RwLock};
 use tracing::info;
 use tree_hash::TreeHash;
-use trin_beacon::initialize_beacon_network;
-use trin_history::initialize_history_network;
-use trin_state::initialize_state_network;
-use trin_storage::PortalStorageConfigFactory;
+use trin_beacon::{initialize_beacon_network, network::BeaconNetwork};
+use trin_history::{initialize_history_network, network::HistoryNetwork};
+use trin_state::{initialize_state_network, network::StateNetwork};
+use trin_storage::{config::StorageCapacityConfig, PortalStorageConfigFactory};
 #[cfg(windows)]
 use trin_utils::cli::Web3TransportType;
 use trin_validation::oracle::HeaderOracle;
 use utp_rs::socket::UtpSocket;
 
-pub async fn run_trin(
+pub async fn run_trin_from_trin_config(
path: bin/trin/src/lib.rs
user: login: morph-dev
body: Seeing that many places use this function and then have to extract and handle `Optional` for rpc_server_handle, how about we do following:

- `TrinHandle::rpc_server_handle` would no longer be `Optional`
- rename `run_trin` to `ruin_trin_internal` (maybe even move it in a separate file)
    - make it non public
    - change return type to `(SubnetworkOverlays, Optional<RpcServerHandle>)`
- create new `run_trin` that doesn't accept `RpcConfig` and only returns `SubnetworkOverlays`
- create new `run_trin_with_rpc` that accepts `RpcConfig` and returns `TrinHandle`
    - `run_trin_from_trin_config` would use `run_trin_with_rpc`

What do you think?
created_at: 2025-04-29T12:00:26Z
author_association: COLLABORATOR
diff_hunk: @@ -146,23 +170,38 @@ pub async fn run_trin(
     };
 
     // Launch JSON-RPC server
-    let jsonrpc_discovery = Arc::clone(&discovery);
-    let rpc_handle: RpcServerHandle = launch_jsonrpc_server(
-        (&trin_config).into(),
-        jsonrpc_discovery,
-        history_jsonrpc_tx,
-        state_jsonrpc_tx,
-        beacon_jsonrpc_tx,
-    )
-    .await?;
+    let rpc_server_handle = if let Some(rpc_config) = rpc_config {
+        let jsonrpc_discovery = Arc::clone(&discovery);
+        Some(
+            launch_jsonrpc_server(
+                rpc_config,
+                node_runtime_config.portal_subnetworks,
+                jsonrpc_discovery,
+                history_jsonrpc_tx,
+                state_jsonrpc_tx,
+                beacon_jsonrpc_tx,
+            )
+            .await?,
+        )
+    } else {
+        None
+    };
+
+    let mut trin_handle = TrinHandle {
+        rpc_server_handle,
+        ..Default::default()
path: bin/trin/src/lib.rs
user: login: morph-dev
body: Why not create SubnetworkOverlays directly:
```rust
SubnetworkOverlays {
    history: history_handler.as_ref().map(|handler| handler.network.clone()),
    // ...
}
```
created_at: 2025-04-29T12:14:56Z
author_association: COLLABORATOR
diff_hunk: @@ -94,7 +91,7 @@ impl FinalizedBootstrap {
 pub struct BeaconBridge {
     consensus_api: ConsensusApi,
     mode: BridgeMode,
-    portal_client: HttpClient,
+    portal_client: SubnetworkOverlays,
path: bin/portal-bridge/src/bridge/beacon.rs
user: login: morph-dev
body: I don't think BeaconBridge should have `SubnetworkOverlays` (as it's annoying to deal with optional).

We would still pass `SubnetworkOverlays` in constructor, but it should only extract and keep `beacon_network: Arc<BeaconNetwork>` (if that's all it needs).

Same for other bridges.
created_at: 2025-04-29T12:21:03Z
author_association: COLLABORATOR
diff_hunk: @@ -70,15 +71,19 @@ impl Default for NetworkInitializationConfig {
 ///
 /// The [Network::init] should be used to initialize our view of the network, and [NetworkManager]
 /// should be used in a background task to keep it up-to-date.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub(super) struct Network {
     peers: Peers<AdditiveWeight>,
-    client: HttpClient,
+    client: SubnetworkOverlays,
path: bin/portal-bridge/src/census/network.rs
user: login: morph-dev
body: We should probably do similar thing here (just keep one network itself), but it's not as easy...
We could probably use `OverlayProtocol` type, but I think we would have to introduce 5 generics (which probably isn't that bad). What do you think?

If you decide that it's too ugly/too much work, we could at least do this:

```rust
pub fn get_overlay_protocol(&self) -> Arc<OverlayProtocol> {
    match self.subnetwork {
        Subnetwork::History => {
            self.client
                .history_overlay()
                .expect(...)
                .overlay
                .clone()
        // ...
    }
}
```
This would make ping, find_nodes and recursive_find_nodes functions almost not needed.

---

Also, "client" name makes no sense anymore.
created_at: 2025-04-29T12:31:21Z
author_association: COLLABORATOR
diff_hunk: @@ -182,6 +181,23 @@ pub struct BridgeConfig {
     pub data_dir: Option<PathBuf>,
 }
 
+impl BridgeConfig {
+    pub fn to_node_runtime_config(&self, node_data_dir: PathBuf) -> NodeRuntimeConfig {
path: bin/portal-bridge/src/cli.rs
user: login: morph-dev
body: nit: maybe `as_node_runtime_config` ? The "to" and "into" usually take ownership of `self` while `as_` don't.

Of just implement `impl From<&BridgeConfig> for NodeRuntimeConfig`.
created_at: 2025-04-29T12:39:28Z
author_association: COLLABORATOR
diff_hunk: @@ -381,6 +383,32 @@ impl TrinConfig {
             },
         }
     }
+
+    pub fn to_portalnet_config(&self, private_key: B256) -> PortalnetConfig {
path: bin/trin/src/cli.rs
user: login: morph-dev
body: nit: Also here, maybe `as_portalnet_config`?
created_at: 2025-04-29T12:40:29Z
author_association: COLLABORATOR
diff_hunk: @@ -381,6 +383,32 @@ impl TrinConfig {
             },
         }
     }
+
+    pub fn to_portalnet_config(&self, private_key: B256) -> PortalnetConfig {
+        PortalnetConfig {
+            external_addr: self.external_addr,
+            private_key,
+            listen_port: self.discovery_port,
+            bootnodes: self.bootnodes.to_enrs(self.network.network()),
+            no_stun: self.no_stun,
+            no_upnp: self.no_upnp,
+            discv5_session_cache_capacity: DISCV5_SESSION_CACHE_CAPACITY,
+            disable_poke: self.disable_poke,
+            trusted_block_root: self.trusted_block_root,
+            utp_transfer_limit: self.utp_transfer_limit,
+        }
+    }
+
+    pub fn to_node_runtime_config(&self, node_data_dir: PathBuf) -> NodeRuntimeConfig {
path: bin/trin/src/cli.rs
user: login: morph-dev
body: nit: and here
created_at: 2025-04-29T12:40:36Z
author_association: COLLABORATOR
diff_hunk: @@ -54,6 +53,17 @@ trin-utils.workspace = true
 trin-validation.workspace = true
 url.workspace = true
 
+# Trin dependencies
path: bin/portal-bridge/Cargo.toml
user: login: KolbyML
body: > Why not keep them together?
> 
> If you want to propose that crates from this repo should be separated from external crates, then we should do it for all crates, not just bridge (and that should definitely be separate PR). I personally don't see much value in doing this and don't think that we should do it, but I wouldn't oppose it.

It is easier to what what crates are ours

> Also, why is `utp-rs` here and `eth_trie` is not?

both utp-rs and eth_trie shouldn't be in this section as those crates aren't in our workspace, I mistakenly put utp-rs there
created_at: 2025-04-30T01:57:51Z
author_association: MEMBER
diff_hunk: @@ -54,6 +53,17 @@ trin-utils.workspace = true
 trin-validation.workspace = true
 url.workspace = true
 
+# Trin dependencies
path: bin/portal-bridge/Cargo.toml
user: login: KolbyML
body: I will revert it for now I guess
created_at: 2025-04-30T01:58:01Z
author_association: MEMBER
diff_hunk: @@ -182,6 +181,23 @@ pub struct BridgeConfig {
     pub data_dir: Option<PathBuf>,
 }
 
+impl BridgeConfig {
+    pub fn to_node_runtime_config(&self, node_data_dir: PathBuf) -> NodeRuntimeConfig {
path: bin/portal-bridge/src/cli.rs
user: login: KolbyML
body: > nit: maybe `as_node_runtime_config` ? The "to" and "into" usually take ownership of `self` while `as_` don't.

sure

> Of just implement `impl From<&BridgeConfig> for NodeRuntimeConfig`.

I am passing in `node_data_dir` so I can't use the from trait
created_at: 2025-04-30T02:06:36Z
author_association: MEMBER
diff_hunk: @@ -3,42 +3,37 @@
 
 pub mod cli;
 
-use std::sync::Arc;
+use std::{net::SocketAddr, path::PathBuf, sync::Arc};
 
+use anyhow::bail;
 use cli::TrinConfig;
 use ethportal_api::{
-    types::{distance::Distance, network::Subnetwork},
+    types::{distance::Distance, network::Subnetwork, network_spec::NetworkSpec},
     utils::bytes::hex_encode,
     version::get_trin_version,
 };
 use portalnet::{
+    config::PortalnetConfig,
     discovery::{Discovery, Discv5UdpSocket},
     events::PortalnetEvents,
     utils::db::{configure_node_data_dir, configure_trin_data_dir},
 };
-use rpc::{launch_jsonrpc_server, RpcServerHandle};
+use rpc::{config::RpcConfig, launch_jsonrpc_server, RpcServerHandle};
 use tokio::sync::{mpsc, RwLock};
 use tracing::info;
 use tree_hash::TreeHash;
-use trin_beacon::initialize_beacon_network;
-use trin_history::initialize_history_network;
-use trin_state::initialize_state_network;
-use trin_storage::PortalStorageConfigFactory;
+use trin_beacon::{initialize_beacon_network, network::BeaconNetwork};
+use trin_history::{initialize_history_network, network::HistoryNetwork};
+use trin_state::{initialize_state_network, network::StateNetwork};
+use trin_storage::{config::StorageCapacityConfig, PortalStorageConfigFactory};
 #[cfg(windows)]
 use trin_utils::cli::Web3TransportType;
 use trin_validation::oracle::HeaderOracle;
 use utp_rs::socket::UtpSocket;
 
-pub async fn run_trin(
+pub async fn run_trin_from_trin_config(
path: bin/trin/src/lib.rs
user: login: KolbyML
body: Sure sounds good
created_at: 2025-04-30T05:56:50Z
author_association: MEMBER
diff_hunk: @@ -94,7 +91,7 @@ impl FinalizedBootstrap {
 pub struct BeaconBridge {
     consensus_api: ConsensusApi,
     mode: BridgeMode,
-    portal_client: HttpClient,
+    portal_client: SubnetworkOverlays,
path: bin/portal-bridge/src/bridge/beacon.rs
user: login: KolbyML
body: I passed in the respective network into the constructor, as `SubnetworkOverlays` is a bit to broad I feel for the constructor, we might as well fully commit if we go this path. Which I agree it is good
created_at: 2025-04-30T06:07:37Z
author_association: MEMBER
diff_hunk: @@ -70,15 +71,19 @@ impl Default for NetworkInitializationConfig {
 ///
 /// The [Network::init] should be used to initialize our view of the network, and [NetworkManager]
 /// should be used in a background task to keep it up-to-date.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub(super) struct Network {
     peers: Peers<AdditiveWeight>,
-    client: HttpClient,
+    client: SubnetworkOverlays,
path: bin/portal-bridge/src/census/network.rs
user: login: KolbyML
body: I ended up just moving those functions into the `SubnetworkOverlays` struct
![image](https://github.com/user-attachments/assets/d25045b2-3de7-48f7-aaec-798f9cbbb946)

5 generics is way too much, I would like to avoid it if possible
created_at: 2025-04-30T06:31:20Z
author_association: MEMBER
diff_hunk: @@ -52,14 +42,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 bridge_config.request_timeout,
             )
             .await?;
-            let portal_client_clone = portal_client.clone();
+            let Some(beacon_network) = subnetwork_overlays.beacon else {
+                panic!("Beacon network not found in SubnetworkOverlays");
+            };
path: bin/portal-bridge/src/main.rs
user: login: morph-dev
body: ```suggestion
            let beacon_network = subnetwork_overlays.beacon
                .expect("Beacon network not found in SubnetworkOverlays");
```

I think this is cleaner. Same below for history and state.
created_at: 2025-04-30T11:19:52Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+use std::sync::Arc;
+
+use anyhow::{anyhow, bail};
+use discv5::{enr::NodeId, Enr};
+use ethportal_api::types::{network::Subnetwork, portal_wire::Pong};
+use rpc::RpcServerHandle;
+use trin_beacon::network::BeaconNetwork;
+use trin_history::network::HistoryNetwork;
+use trin_state::network::StateNetwork;
+
+pub struct TrinHandle {
+    pub rpc_server_handle: RpcServerHandle,
+    pub subnetwork_overlays: SubnetworkOverlays,
+}
+
+#[derive(Default, Clone)]
+pub struct SubnetworkOverlays {
+    pub history: Option<Arc<HistoryNetwork>>,
+    pub state: Option<Arc<StateNetwork>>,
+    pub beacon: Option<Arc<BeaconNetwork>>,
+}
+
+impl SubnetworkOverlays {
+    pub fn history_overlay(&self) -> anyhow::Result<Arc<HistoryNetwork>> {
+        match &self.history {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("History network is not available"),
+        }
path: bin/trin/src/handle.rs
user: login: morph-dev
body: ```suggestion
        self.history.clone().ok_or_else(|| anyhow!("History network is not available"))
```

nit: I think this is simpler, but up to you.
Also, I would rename function to just `history()` or actually return `OverlayProtocol` (otherwise we have `.history_overlay().overlay`)

Same below.
created_at: 2025-04-30T11:28:42Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+use std::sync::Arc;
+
+use anyhow::{anyhow, bail};
+use discv5::{enr::NodeId, Enr};
+use ethportal_api::types::{network::Subnetwork, portal_wire::Pong};
+use rpc::RpcServerHandle;
+use trin_beacon::network::BeaconNetwork;
+use trin_history::network::HistoryNetwork;
+use trin_state::network::StateNetwork;
+
+pub struct TrinHandle {
+    pub rpc_server_handle: RpcServerHandle,
+    pub subnetwork_overlays: SubnetworkOverlays,
+}
+
+#[derive(Default, Clone)]
+pub struct SubnetworkOverlays {
+    pub history: Option<Arc<HistoryNetwork>>,
+    pub state: Option<Arc<StateNetwork>>,
+    pub beacon: Option<Arc<BeaconNetwork>>,
+}
+
+impl SubnetworkOverlays {
+    pub fn history_overlay(&self) -> anyhow::Result<Arc<HistoryNetwork>> {
+        match &self.history {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("History network is not available"),
+        }
+    }
+
+    pub fn state_overlay(&self) -> anyhow::Result<Arc<StateNetwork>> {
+        match &self.state {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("State network is not available"),
+        }
+    }
+
+    pub fn beacon_overlay(&self) -> anyhow::Result<Arc<BeaconNetwork>> {
+        match &self.beacon {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("Beacon network is not available"),
+        }
+    }
+
+    pub async fn ping(&self, subnetwork: Subnetwork, enr: &Enr) -> anyhow::Result<Pong> {
path: bin/trin/src/handle.rs
user: login: morph-dev
body: I don't see value in these functions. One can easily do:
`subnetwork_overlays.<subnetwork>_overlay()?.overlay.ping`
Also this file will keep growing if we keep adding things.

I would rather move this back in `bin/portal-bridge/src/census/network.rs`, instead of encouraging usage from here. I think we some magic with generics we could make it nicer, but I don't see it right now (and it's not big deal anyway).

Up to you.
created_at: 2025-04-30T12:08:36Z
author_association: COLLABORATOR
path: bin/trin/src/builder.rs
user: login: morph-dev
body: Filename doesn't make much sense to me, as we are not building anything. I would rather call it any of the following: run.rs, internal.rs, impl.rs

In my opinion, everything in here except `run_trin_internal` can go in `lib.rs` because it's relatively small (the `run_trin_internal` would be `pub(crate)` or `pub(super)`). If not, then we should at least re-export public functions at the top level.


created_at: 2025-04-30T12:18:49Z
author_association: COLLABORATOR
diff_hunk: @@ -1,194 +1,6 @@
 #![warn(clippy::unwrap_used)]
path: bin/trin/src/lib.rs
user: login: morph-dev
body: nit: can we remove these?
created_at: 2025-04-30T12:19:12Z
author_association: COLLABORATOR
diff_hunk: @@ -102,114 +72,74 @@ impl HeaderOracle {
         }
     }
 
-    pub async fn history_get_enr(
-        node_id: &NodeId,
-        history_jsonrpc_tx: mpsc::UnboundedSender<HistoryJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = HistoryEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = HistoryJsonRpcRequest { endpoint, resp };
-        history_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("History network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from History network")),
-        };
-
-        let enr: Enr = serde_json::from_value(enr_value)?;
-
-        Ok(enr)
-    }
-
-    pub async fn state_get_enr(
-        node_id: &NodeId,
-        state_jsonrpc_tx: mpsc::UnboundedSender<StateJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = StateEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = StateJsonRpcRequest { endpoint, resp };
-        state_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("State network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from State network")),
-        };
-
-        let enr: Enr = serde_json::from_value(enr_value)?;
-
-        Ok(enr)
-    }
-
-    pub async fn beacon_get_enr(
-        node_id: &NodeId,
-        beacon_jsonrpc_tx: mpsc::UnboundedSender<BeaconJsonRpcRequest>,
-    ) -> anyhow::Result<Enr> {
-        let endpoint = BeaconEndpoint::GetEnr(*node_id);
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        beacon_jsonrpc_tx.send(request)?;
-
-        let enr_value = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
+    /// Returns the HeaderWithProof for the given block hash by performing a recursive find content
+    /// request.
+    pub async fn recursive_find_header_by_hash_with_proof(
+        &self,
+        block_hash: B256,
+    ) -> anyhow::Result<HeaderWithProof> {
+        let content_key = HistoryContentKey::new_block_header_by_hash(block_hash);
+        let endpoint = HistoryEndpoint::GetContent(content_key.clone());
 
-        let enr: Enr = serde_json::from_value(enr_value)?;
+        let GetContentInfo { content, .. } = self.send_history_request(endpoint).await?;
+        let content: HistoryContentValue = HistoryContentValue::decode(&content_key, &content)?;
 
-        Ok(enr)
+        match content {
+            HistoryContentValue::BlockHeaderWithProof(content) => Ok(content),
+            _ => Err(anyhow!(
+                "Invalid HistoryContentValue received from HeaderWithProof lookup, expected BlockHeaderWithProof: {content:?}"
+            )),
+        }
     }
 
     /// Return latest finalized root of the beacon state.
     pub async fn get_finalized_state_root(&self) -> anyhow::Result<B256> {
         let endpoint = BeaconEndpoint::FinalizedStateRoot;
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        let tx = self.beacon_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let state_root = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-
-        let state_root: B256 = serde_json::from_value(state_root)?;
-
-        Ok(state_root)
+        self.send_beacon_request(endpoint).await
     }
 
     /// Return latest finalized beacon header.
     pub async fn get_finalized_header(&self) -> anyhow::Result<BeaconBlockHeader> {
         let endpoint = BeaconEndpoint::FinalizedHeader;
-        let (resp, mut resp_rx) = mpsc::unbounded_channel::<Result<Value, String>>();
-        let request = BeaconJsonRpcRequest { endpoint, resp };
-        let tx = self.beacon_jsonrpc_tx()?;
-        tx.send(request)?;
-
-        let header = match resp_rx.recv().await {
-            Some(val) => val.map_err(|err| anyhow!("Beacon network request error: {err:?}"))?,
-            None => return Err(anyhow!("No response from Beacon network")),
-        };
-
-        let header: BeaconBlockHeader = serde_json::from_value(header)?;
-
-        Ok(header)
+        self.send_beacon_request(endpoint).await
     }
 
     /// Return current light client store
     pub async fn get_light_client_store(&self) -> anyhow::Result<LightClientStore> {
         let endpoint = BeaconEndpoint::LightClientStore;
+        self.send_beacon_request(endpoint).await
+    }
+
+    async fn send_history_request<T: for<'a> Deserialize<'a>>(
path: crates/validation/src/oracle.rs
user: login: morph-dev
body: ```suggestion
    async fn send_history_request<T: for<'de> Deserialize<'de>>(
```

nit: we usually use `'de` when using `Deserialize`
created_at: 2025-04-30T12:21:21Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,117 @@
+use std::sync::Arc;
+
+use anyhow::{anyhow, bail};
+use discv5::{enr::NodeId, Enr};
+use ethportal_api::types::{network::Subnetwork, portal_wire::Pong};
+use rpc::RpcServerHandle;
+use trin_beacon::network::BeaconNetwork;
+use trin_history::network::HistoryNetwork;
+use trin_state::network::StateNetwork;
+
+pub struct TrinHandle {
+    pub rpc_server_handle: RpcServerHandle,
+    pub subnetwork_overlays: SubnetworkOverlays,
+}
+
+#[derive(Default, Clone)]
+pub struct SubnetworkOverlays {
+    pub history: Option<Arc<HistoryNetwork>>,
+    pub state: Option<Arc<StateNetwork>>,
+    pub beacon: Option<Arc<BeaconNetwork>>,
+}
+
+impl SubnetworkOverlays {
+    pub fn history_overlay(&self) -> anyhow::Result<Arc<HistoryNetwork>> {
+        match &self.history {
+            Some(overlay) => Ok(overlay.clone()),
+            None => bail!("History network is not available"),
+        }
path: bin/trin/src/handle.rs
user: login: KolbyML
body: I will name it history, as I don't want to return `OverlayProtocol` due to the generics
created_at: 2025-04-30T18:44:16Z
author_association: MEMBER
path: bin/trin/src/builder.rs
user: login: KolbyML
body: I ended up just re-exporting the 3
created_at: 2025-04-30T18:52:14Z
author_association: MEMBER
diff_hunk: @@ -1,194 +1,6 @@
 #![warn(clippy::unwrap_used)]
path: bin/trin/src/lib.rs
user: login: KolbyML
body: I talked to Milos and dm's and there was just some confusion on what this did. He said to ignore this comment
created_at: 2025-04-30T18:56:30Z
author_association: MEMBER
diff_hunk: @@ -1,6 +1,8 @@
 #![warn(clippy::unwrap_used)]
 #![warn(clippy::uninlined_format_args)]
 
-pub mod builder;
 pub mod cli;
 pub mod handle;
+pub mod run;
path: bin/trin/src/lib.rs
user: login: morph-dev
body: Since we are re-exporting all these functions, no need for this module to be public.

To be fair, we can re-export all public structures/functions from this crate, as there aren't that many of them. We moved them into separate files only because this one was growing big.
It makes sense for other crates that want to use these types/functions, to do so at the root (e.g. `trin::TrinConfig` instead of `trin::cli::TrinConfig`).
created_at: 2025-04-30T19:06:24Z
author_association: COLLABORATOR
diff_hunk: @@ -1,6 +1,8 @@
 #![warn(clippy::unwrap_used)]
 #![warn(clippy::uninlined_format_args)]
 
-pub mod builder;
 pub mod cli;
 pub mod handle;
+pub mod run;
path: bin/trin/src/lib.rs
user: login: KolbyML
body: Sure, done
created_at: 2025-04-30T19:18:54Z
author_association: MEMBER

PR comments:
user: login: KolbyML
created_at: 2025-04-29T04:17:29Z
body: > I reviewed entire PR quickly and I don't want all this functionality in HeaderOracle.
> 
> Also, if I'm not mistaken, we are still converting requests/responses to/from JSON, right? What do you think about getting `Arc<OverlayProtocol<...>>` (e.g. `history_handler.network.overlay.clone()`) and using it directly? Or do you think that is value in using high level API?
 
I think this is a great idea :rocket: 

> I agree that current bridge peertest isn't testing much. But I believe that we should have some bridge peertests in place. I don't expect this to be done in this PR. I don't expect this to be done in the next PR because it isn't a priority. But I believe we should make a issue to track it so we don't completely forget about it.

Sure I can make an issue
author_association: MEMBER
user: login: KolbyML
created_at: 2025-04-29T05:51:10Z
body: @morph-dev ready for another review
author_association: MEMBER
user: login: KolbyML
created_at: 2025-04-29T06:25:56Z
body: I made an issue https://github.com/ethereum/trin/issues/1793
author_association: MEMBER
user: login: KolbyML
created_at: 2025-04-30T06:43:07Z
body: @morph-dev ready for another review
author_association: MEMBER
user: login: KolbyML
created_at: 2025-04-30T18:59:55Z
body: @morph-dev ready for another look
author_association: MEMBER