From 2aa45a7c698ce3f9c3f3fe7699bd4b6e8f8aefd9 Mon Sep 17 00:00:00 2001 From: Hector Bulgarini Date: Sun, 18 Aug 2024 18:01:03 +0200 Subject: [PATCH] wip --- Cargo.lock | 2 + system-parachains/bridge-hub-paseo/Cargo.toml | 332 +++++---- system-parachains/bridge-hub-paseo/build.rs | 8 +- .../bridge-hub-paseo/primitives/Cargo.toml | 17 +- .../bridge-hub-paseo/primitives/src/lib.rs | 174 +---- .../src/bridge_to_ethereum_config.rs | 248 +++---- .../src/bridge_to_ethereum_unstuck.rs | 122 ---- .../src/bridge_to_kusama_config.rs | 428 ----------- .../src/bridge_to_kusama_unstuck.rs | 110 --- system-parachains/bridge-hub-paseo/src/lib.rs | 689 +++++++----------- .../src/weights/block_weights.rs | 2 +- .../cumulus_pallet_parachain_system.rs | 54 +- .../src/weights/cumulus_pallet_xcmp_queue.rs | 34 +- .../src/weights/extrinsic_weights.rs | 2 +- .../src/weights/frame_system.rs | 78 +- .../bridge-hub-paseo/src/weights/mod.rs | 31 - .../src/weights/pallet_balances.rs | 46 +- .../src/weights/pallet_bridge_grandpa.rs | 77 -- .../src/weights/pallet_bridge_messages.rs | 240 ------ .../src/weights/pallet_bridge_parachains.rs | 110 --- .../src/weights/pallet_bridge_relayers.rs | 121 --- .../src/weights/pallet_collator_selection.rs | 94 +-- .../src/weights/pallet_multisig.rs | 83 +-- .../src/weights/pallet_timestamp.rs | 25 +- .../src/weights/pallet_xcm.rs | 200 ++--- .../snowbridge_pallet_ethereum_client.rs | 8 +- .../snowbridge_pallet_inbound_queue.rs | 2 +- .../snowbridge_pallet_outbound_queue.rs | 6 +- .../src/weights/snowbridge_pallet_system.rs | 20 +- .../bridge-hub-paseo/src/weights/xcm/mod.rs | 8 +- .../xcm/pallet_xcm_benchmarks_fungible.rs | 79 +- .../xcm/pallet_xcm_benchmarks_generic.rs | 198 +++-- .../bridge-hub-paseo/src/xcm_config.rs | 387 +++++----- .../bridge-hub-paseo/tests/snowbridge.rs | 677 +++++++++-------- .../bridge-hub-paseo/tests/tests.rs | 425 ----------- 35 files changed, 1569 insertions(+), 3568 deletions(-) delete mode 100644 system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_unstuck.rs delete mode 100644 system-parachains/bridge-hub-paseo/src/bridge_to_kusama_config.rs delete mode 100644 system-parachains/bridge-hub-paseo/src/bridge_to_kusama_unstuck.rs delete mode 100644 system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_grandpa.rs delete mode 100644 system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_messages.rs delete mode 100644 system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_parachains.rs delete mode 100644 system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_relayers.rs delete mode 100644 system-parachains/bridge-hub-paseo/tests/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 004cfa1..9b183b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -627,6 +627,7 @@ dependencies = [ "sp-block-builder", "sp-consensus-aura", "sp-core", + "sp-debug-derive", "sp-genesis-builder", "sp-inherents", "sp-io", @@ -1426,6 +1427,7 @@ dependencies = [ "sp-block-builder", "sp-consensus-aura", "sp-core", + "sp-debug-derive", "sp-genesis-builder", "sp-inherents", "sp-io", diff --git a/system-parachains/bridge-hub-paseo/Cargo.toml b/system-parachains/bridge-hub-paseo/Cargo.toml index db4ad96..f1bc34a 100644 --- a/system-parachains/bridge-hub-paseo/Cargo.toml +++ b/system-parachains/bridge-hub-paseo/Cargo.toml @@ -1,10 +1,10 @@ [package] authors.workspace = true build = "build.rs" -description = "Polkadot's BridgeHub parachain runtime" +description = "Paseo's BridgeHub parachain runtime" edition.workspace = true license.workspace = true -name = "bridge-hub-polkadot-runtime" +name = "bridge-hub-paseo-runtime" repository.workspace = true version.workspace = true @@ -19,12 +19,9 @@ scale-info = { features = ["derive"], workspace = true } serde = { optional = true, features = ["derive"], workspace = true } # Local -bp-asset-hub-kusama = { workspace = true } -bp-asset-hub-polkadot = { workspace = true } -bp-bridge-hub-kusama = { workspace = true } -bp-bridge-hub-polkadot = { workspace = true } -kusama-runtime-constants = { workspace = true } -polkadot-runtime-constants = { workspace = true } +bp-asset-hub-paseo = { workspace = true } +bp-bridge-hub-paseo = { workspace = true } +paseo-runtime-constants = { workspace = true } # Substrate frame-benchmarking = { optional = true, workspace = true } @@ -73,7 +70,7 @@ xcm-executor = { workspace = true } # Cumulus cumulus-pallet-aura-ext = { workspace = true } cumulus-pallet-parachain-system = { features = [ - "parameterized-consensus-hook", + "parameterized-consensus-hook", ], workspace = true } cumulus-pallet-session-benchmarking = { workspace = true } cumulus-pallet-xcm = { workspace = true } @@ -115,10 +112,12 @@ snowbridge-outbound-queue-runtime-api = { workspace = true } snowbridge-router-primitives = { workspace = true } snowbridge-runtime-common = { workspace = true } +sp-debug-derive = { workspace = true } + [dev-dependencies] bridge-hub-test-utils = { workspace = true } bridge-runtime-common = { features = [ - "integrity-test", + "integrity-test", ], workspace = true, default-features = true } sp-keyring = { workspace = true } static_assertions = { workspace = true } @@ -128,169 +127,167 @@ parachains-runtimes-test-utils = { workspace = true } [features] default = ["std"] std = [ - "bp-asset-hub-kusama/std", - "bp-asset-hub-polkadot/std", - "bp-bridge-hub-kusama/std", - "bp-bridge-hub-polkadot/std", - "bp-header-chain/std", - "bp-kusama/std", - "bp-messages/std", - "bp-parachains/std", - "bp-polkadot-core/std", - "bp-polkadot/std", - "bp-relayers/std", - "bp-runtime/std", - "bridge-hub-common/std", - "bridge-runtime-common/std", - "codec/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-session-benchmarking/std", - "cumulus-pallet-xcm/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-primitives-aura/std", - "cumulus-primitives-core/std", - "cumulus-primitives-utility/std", - "frame-benchmarking?/std", - "frame-executive/std", - "frame-metadata-hash-extension/std", - "frame-support/std", - "frame-system-benchmarking?/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "frame-try-runtime?/std", - "kusama-runtime-constants/std", - "log/std", - "pallet-aura/std", - "pallet-authorship/std", - "pallet-balances/std", - "pallet-bridge-grandpa/std", - "pallet-bridge-messages/std", - "pallet-bridge-parachains/std", - "pallet-bridge-relayers/std", - "pallet-collator-selection/std", - "pallet-message-queue/std", - "pallet-multisig/std", - "pallet-session/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-utility/std", - "pallet-xcm-benchmarks?/std", - "pallet-xcm-bridge-hub/std", - "pallet-xcm/std", - "parachain-info/std", - "parachains-common/std", - "polkadot-core-primitives/std", - "polkadot-parachain-primitives/std", - "polkadot-runtime-common/std", - "polkadot-runtime-constants/std", - "scale-info/std", - "serde", - "snowbridge-beacon-primitives/std", - "snowbridge-core/std", - "snowbridge-outbound-queue-runtime-api/std", - "snowbridge-pallet-ethereum-client/std", - "snowbridge-pallet-inbound-queue/std", - "snowbridge-pallet-outbound-queue/std", - "snowbridge-pallet-system/std", - "snowbridge-router-primitives/std", - "snowbridge-runtime-common/std", - "snowbridge-system-runtime-api/std", - "sp-api/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-genesis-builder/std", - "sp-inherents/std", - "sp-io/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-storage/std", - "sp-transaction-pool/std", - "sp-version/std", - "substrate-wasm-builder", - "system-parachains-constants/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", + "bp-asset-hub-paseo/std", + "bp-bridge-hub-paseo/std", + "bp-header-chain/std", + "bp-kusama/std", + "bp-messages/std", + "bp-parachains/std", + "bp-polkadot-core/std", + "bp-polkadot/std", + "bp-relayers/std", + "bp-runtime/std", + "bridge-hub-common/std", + "bridge-runtime-common/std", + "codec/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-aura/std", + "cumulus-primitives-core/std", + "cumulus-primitives-utility/std", + "frame-benchmarking?/std", + "frame-executive/std", + "frame-metadata-hash-extension/std", + "frame-support/std", + "frame-system-benchmarking?/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime?/std", + "paseo-runtime-constants/std", + "log/std", + "pallet-aura/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-bridge-grandpa/std", + "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", + "pallet-collator-selection/std", + "pallet-message-queue/std", + "pallet-multisig/std", + "pallet-session/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-utility/std", + "pallet-xcm-benchmarks?/std", + "pallet-xcm-bridge-hub/std", + "pallet-xcm/std", + "parachain-info/std", + "parachains-common/std", + "polkadot-core-primitives/std", + "polkadot-parachain-primitives/std", + "polkadot-runtime-common/std", + "scale-info/std", + "serde", + "snowbridge-beacon-primitives/std", + "snowbridge-core/std", + "snowbridge-outbound-queue-runtime-api/std", + "snowbridge-pallet-ethereum-client/std", + "snowbridge-pallet-inbound-queue/std", + "snowbridge-pallet-outbound-queue/std", + "snowbridge-pallet-system/std", + "snowbridge-router-primitives/std", + "snowbridge-runtime-common/std", + "snowbridge-system-runtime-api/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-debug-derive/std", + "sp-core/std", + "sp-genesis-builder/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-storage/std", + "sp-transaction-pool/std", + "sp-version/std", + "substrate-wasm-builder", + "system-parachains-constants/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", ] runtime-benchmarks = [ - "bridge-hub-common/runtime-benchmarks", - "bridge-runtime-common/runtime-benchmarks", - "cumulus-pallet-parachain-system/runtime-benchmarks", - "cumulus-pallet-session-benchmarking/runtime-benchmarks", - "cumulus-pallet-xcmp-queue/runtime-benchmarks", - "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-utility/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-bridge-grandpa/runtime-benchmarks", - "pallet-bridge-messages/runtime-benchmarks", - "pallet-bridge-parachains/runtime-benchmarks", - "pallet-bridge-relayers/runtime-benchmarks", - "pallet-collator-selection/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-multisig/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", - "pallet-xcm-benchmarks/runtime-benchmarks", - "pallet-xcm-bridge-hub/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "parachains-common/runtime-benchmarks", - "polkadot-parachain-primitives/runtime-benchmarks", - "polkadot-runtime-common/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "snowbridge-pallet-ethereum-client/runtime-benchmarks", - "snowbridge-pallet-inbound-queue/runtime-benchmarks", - "snowbridge-pallet-outbound-queue/runtime-benchmarks", - "snowbridge-pallet-system/runtime-benchmarks", - "snowbridge-router-primitives/runtime-benchmarks", - "snowbridge-runtime-common/runtime-benchmarks", - "snowbridge-runtime-test-common/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", + "bridge-hub-common/runtime-benchmarks", + "bridge-runtime-common/runtime-benchmarks", + "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-utility/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-xcm-benchmarks/runtime-benchmarks", + "pallet-xcm-bridge-hub/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "parachains-common/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", + "snowbridge-core/runtime-benchmarks", + "snowbridge-pallet-ethereum-client/runtime-benchmarks", + "snowbridge-pallet-inbound-queue/runtime-benchmarks", + "snowbridge-pallet-outbound-queue/runtime-benchmarks", + "snowbridge-pallet-system/runtime-benchmarks", + "snowbridge-router-primitives/runtime-benchmarks", + "snowbridge-runtime-common/runtime-benchmarks", + "snowbridge-runtime-test-common/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", ] try-runtime = [ - "cumulus-pallet-aura-ext/try-runtime", - "cumulus-pallet-parachain-system/try-runtime", - "cumulus-pallet-xcm/try-runtime", - "cumulus-pallet-xcmp-queue/try-runtime", - "frame-executive/try-runtime", - "frame-support/try-runtime", - "frame-system/try-runtime", - "frame-try-runtime/try-runtime", - "pallet-aura/try-runtime", - "pallet-authorship/try-runtime", - "pallet-balances/try-runtime", - "pallet-bridge-grandpa/try-runtime", - "pallet-bridge-messages/try-runtime", - "pallet-bridge-parachains/try-runtime", - "pallet-bridge-relayers/try-runtime", - "pallet-collator-selection/try-runtime", - "pallet-message-queue/try-runtime", - "pallet-multisig/try-runtime", - "pallet-session/try-runtime", - "pallet-timestamp/try-runtime", - "pallet-transaction-payment/try-runtime", - "pallet-utility/try-runtime", - "pallet-xcm-bridge-hub/try-runtime", - "pallet-xcm/try-runtime", - "parachain-info/try-runtime", - "polkadot-runtime-common/try-runtime", - "snowbridge-pallet-ethereum-client/try-runtime", - "snowbridge-pallet-inbound-queue/try-runtime", - "snowbridge-pallet-outbound-queue/try-runtime", - "snowbridge-pallet-system/try-runtime", - "sp-runtime/try-runtime", + "cumulus-pallet-aura-ext/try-runtime", + "cumulus-pallet-parachain-system/try-runtime", + "cumulus-pallet-xcm/try-runtime", + "cumulus-pallet-xcmp-queue/try-runtime", + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-aura/try-runtime", + "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", + "pallet-bridge-grandpa/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-parachains/try-runtime", + "pallet-bridge-relayers/try-runtime", + "pallet-collator-selection/try-runtime", + "pallet-message-queue/try-runtime", + "pallet-multisig/try-runtime", + "pallet-session/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", + "pallet-utility/try-runtime", + "pallet-xcm-bridge-hub/try-runtime", + "pallet-xcm/try-runtime", + "parachain-info/try-runtime", + "polkadot-runtime-common/try-runtime", + "snowbridge-pallet-ethereum-client/try-runtime", + "snowbridge-pallet-inbound-queue/try-runtime", + "snowbridge-pallet-outbound-queue/try-runtime", + "snowbridge-pallet-system/try-runtime", + "sp-runtime/try-runtime", ] # Enable metadata hash generation at compile time for the `CheckMetadataHash` extension. @@ -300,3 +297,4 @@ metadata-hash = ["substrate-wasm-builder?/metadata-hash"] # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. on-chain-release-build = ["sp-api/disable-logging", "metadata-hash"] +force-debug = ["sp-debug-derive/force-debug"] diff --git a/system-parachains/bridge-hub-paseo/build.rs b/system-parachains/bridge-hub-paseo/build.rs index e65608b..a9ba6c2 100644 --- a/system-parachains/bridge-hub-paseo/build.rs +++ b/system-parachains/bridge-hub-paseo/build.rs @@ -15,14 +15,14 @@ #[cfg(all(feature = "std", not(feature = "metadata-hash")))] fn main() { - substrate_wasm_builder::WasmBuilder::build_using_defaults() + substrate_wasm_builder::WasmBuilder::build_using_defaults() } #[cfg(all(feature = "std", feature = "metadata-hash"))] fn main() { - substrate_wasm_builder::WasmBuilder::init_with_defaults() - .enable_metadata_hash("DOT", 10) - .build() + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("PAS", 12) + .build() } #[cfg(not(feature = "std"))] diff --git a/system-parachains/bridge-hub-paseo/primitives/Cargo.toml b/system-parachains/bridge-hub-paseo/primitives/Cargo.toml index 404058b..904a3d7 100644 --- a/system-parachains/bridge-hub-paseo/primitives/Cargo.toml +++ b/system-parachains/bridge-hub-paseo/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "bp-bridge-hub-polkadot" -description = "Primitives of BridgeHubPolkadot parachain runtime." +name = "bp-bridge-hub-paseo" +description = "Primitives of BridgeHub Paseo parachain runtime." repository.workspace = true version.workspace = true authors.workspace = true @@ -8,13 +8,9 @@ edition.workspace = true license.workspace = true [dependencies] - -# Local -kusama-runtime-constants = { workspace = true } -polkadot-runtime-constants = { workspace = true } -system-parachains-constants = { workspace = true } - # Bridge Dependencies +codec = { package = "parity-scale-codec", version = "3.6.12", default-features = false } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } bp-bridge-hub-cumulus = { workspace = true } bp-runtime = { workspace = true } bp-messages = { workspace = true } @@ -36,12 +32,11 @@ std = [ "bp-messages/std", "bp-runtime/std", "frame-support/std", - "kusama-runtime-constants/std", - "polkadot-runtime-constants/std", "snowbridge-core/std", "sp-api/std", "sp-runtime/std", "sp-std/std", - "system-parachains-constants/std", "xcm/std", + "codec/std", + "scale-info/std" ] diff --git a/system-parachains/bridge-hub-paseo/primitives/src/lib.rs b/system-parachains/bridge-hub-paseo/primitives/src/lib.rs index ac289f6..203d6d3 100644 --- a/system-parachains/bridge-hub-paseo/primitives/src/lib.rs +++ b/system-parachains/bridge-hub-paseo/primitives/src/lib.rs @@ -20,151 +20,24 @@ #![cfg_attr(not(feature = "std"), no_std)] pub use bp_bridge_hub_cumulus::*; -use bp_messages::*; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain, -}; -use frame_support::dispatch::DispatchClass; -use sp_runtime::{FixedPointNumber, FixedU128, RuntimeDebug, Saturating}; - -/// BridgeHubPolkadot parachain. -#[derive(RuntimeDebug)] -pub struct BridgeHubPolkadot; - -impl Chain for BridgeHubPolkadot { - const ID: ChainId = *b"bhpd"; - - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) - } - - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) - } -} - -impl Parachain for BridgeHubPolkadot { - const PARACHAIN_ID: u32 = BRIDGE_HUB_POLKADOT_PARACHAIN_ID; -} - -impl ChainWithMessages for BridgeHubPolkadot { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -} - -/// Identifier of BridgeHubPolkadot in the Polkadot relay chain. -pub const BRIDGE_HUB_POLKADOT_PARACHAIN_ID: u32 = 1002; - -/// Name of the With-BridgeHubPolkadot messages pallet instance that is deployed at bridged chains. -pub const WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; - -/// Name of the With-BridgeHubPolkadot bridge-relayers pallet instance that is deployed at bridged -/// chains. -pub const WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; - -/// Pallet index of `BridgeKusamaMessages: pallet_bridge_messages::`. -pub const WITH_BRIDGE_POLKADOT_TO_KUSAMA_MESSAGES_PALLET_INDEX: u8 = 53; - -decl_bridge_finality_runtime_apis!(bridge_hub_polkadot); -decl_bridge_messages_runtime_apis!(bridge_hub_polkadot); - -frame_support::parameter_types! { - /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Polkadot - /// BridgeHub. - /// (initially was calculated by test `BridgeHubPolkadot::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubPolkadotBaseXcmFeeInDots: Balance = 177_594_900; - - /// Transaction fee that is paid at the Polkadot BridgeHub for delivering single inbound message. - /// (initially was calculated by test `BridgeHubPolkadot::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) - pub const BridgeHubPolkadotBaseDeliveryFeeInDots: Balance = 16_912_645_364; - - /// Transaction fee that is paid at the Polkadot BridgeHub for delivering single outbound message confirmation. - /// (initially was calculated by test `BridgeHubPolkadot::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubPolkadotBaseConfirmationFeeInDots: Balance = 16_142_774_864; -} - -/// Compute the total estimated fee that needs to be paid in DOTs by the sender when sending -/// message from Polkadot Bridge Hub to Kusama Bridge Hub. -pub fn estimate_polkadot_to_kusama_message_fee( - bridge_hub_kusama_base_delivery_fee_in_uksms: Balance, -) -> Balance { - // Sender must pay: - // - // 1) an approximate cost of XCM execution (`ExportMessage` and surroundings) at Polkadot bridge - // Hub; - // - // 2) the approximate cost of Polkadot -> Kusama message delivery transaction on Kusama Bridge - // Hub, converted into KSMs using 1:5 conversion rate; - // - // 3) the approximate cost of Polkadot -> Kusama message confirmation transaction on Polkadot - // Bridge Hub. - BridgeHubPolkadotBaseXcmFeeInDots::get() - .saturating_add(convert_from_uksm_to_udot(bridge_hub_kusama_base_delivery_fee_in_uksms)) - .saturating_add(BridgeHubPolkadotBaseConfirmationFeeInDots::get()) -} - -/// Compute the per-byte fee that needs to be paid in DOTs by the sender when sending -/// message from Polkadot Bridge Hub to Kusama Bridge Hub. -pub fn estimate_polkadot_to_kusama_byte_fee() -> Balance { - // the sender pays for the same byte twice: - // 1) the first part comes from the HRMP, when message travels from Polkadot Asset Hub to - // Polkadot Bridge Hub; - // 2) the second part is the payment for bytes of the message delivery transaction, which is - // "mined" at Kusama Bridge Hub. Hence, we need to use byte fees from that chain and convert - // it to DOTs here. - convert_from_uksm_to_udot(system_parachains_constants::kusama::fee::TRANSACTION_BYTE_FEE) -} - -/// Convert from uKSMs to uDOTs. -fn convert_from_uksm_to_udot(price_in_uksm: Balance) -> Balance { - // assuming exchange rate is 5 DOTs for 1 KSM - let dot_to_ksm_economic_rate = FixedU128::from_rational(5, 1); - // tokens have different nominals and we need to take that into account - let nominal_ratio = FixedU128::from_rational( - polkadot_runtime_constants::currency::UNITS, - kusama_runtime_constants::currency::UNITS, - ); - - dot_to_ksm_economic_rate - .saturating_mul(nominal_ratio) - .saturating_mul(FixedU128::saturating_from_integer(price_in_uksm)) - .into_inner() / - FixedU128::DIV -} +pub const BRIDGE_HUB_PASEO_PARACHAIN_ID: u32 = 1002; pub mod snowbridge { - use crate::Balance; - use frame_support::parameter_types; - use snowbridge_core::{PricingParameters, Rewards, U256}; - use sp_runtime::FixedU128; - use xcm::latest::NetworkId; + use crate::Balance; + use frame_support::parameter_types; + use snowbridge_core::{PricingParameters, Rewards, U256}; + use sp_runtime::FixedU128; + use xcm::latest::NetworkId; - parameter_types! { + parameter_types! { /// Should match the `ForeignAssets::create` index on Asset Hub. pub const CreateAssetCall: [u8;2] = [53, 0]; /// The pallet index of the Ethereum inbound queue pallet in the Bridge Hub runtime. pub const InboundQueuePalletInstance: u8 = 80; /// Default pricing parameters used to calculate bridging fees. Initialized to unit values, - /// as it is intended that these parameters should be updated with more - /// accurate values prior to bridge activation. This can be performed - /// using the `EthereumSystem::set_pricing_parameters` governance extrinsic. + /// as it is intended that these parameters should be updated with more + /// accurate values prior to bridge activation. This can be performed + /// using the `EthereumSystem::set_pricing_parameters` governance extrinsic. pub Parameters: PricingParameters = PricingParameters { // ETH/DOT exchange rate exchange_rate: FixedU128::from_rational(1, 1), @@ -181,28 +54,9 @@ pub mod snowbridge { multiplier: FixedU128::from_rational(1, 1), }; /// Network and location for the Ethereum chain. On Polkadot, the Ethereum chain bridged - /// to is the Ethereum Main network, with chain ID 1. - /// - /// - pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 1 }; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn convert_from_uksm_to_udot_works() { - let price_in_uksm = 77 * kusama_runtime_constants::currency::UNITS; - let same_price_in_udot = convert_from_uksm_to_udot(price_in_uksm); - - let price_in_ksm = - FixedU128::from_rational(price_in_uksm, kusama_runtime_constants::currency::UNITS); - let price_in_dot = FixedU128::from_rational( - same_price_in_udot, - polkadot_runtime_constants::currency::UNITS, - ); - assert_eq!(price_in_dot / FixedU128::saturating_from_integer(5), price_in_ksm); + /// to is the Ethereum Main network, with chain ID 1. + /// + /// + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 }; } } diff --git a/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_config.rs b/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_config.rs index 25aaa8f..047f4b0 100644 --- a/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_config.rs +++ b/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_config.rs @@ -15,13 +15,13 @@ // along with Cumulus. If not, see . use crate::{ - xcm_config, - xcm_config::{RelayTreasuryPalletAccount, UniversalLocation}, - Balances, EthereumInboundQueue, EthereumOutboundQueue, EthereumSystem, MessageQueue, Runtime, - RuntimeEvent, TransactionByteFee, + xcm_config, + xcm_config::{RelayTreasuryPalletAccount, UniversalLocation}, + Balances, EthereumInboundQueue, EthereumOutboundQueue, EthereumSystem, MessageQueue, Runtime, + RuntimeEvent, TransactionByteFee, }; -pub use bp_bridge_hub_polkadot::snowbridge::EthereumNetwork; -use bp_bridge_hub_polkadot::snowbridge::{CreateAssetCall, InboundQueuePalletInstance, Parameters}; +pub use bp_bridge_hub_paseo::snowbridge::EthereumNetwork; +use bp_bridge_hub_paseo::snowbridge::{CreateAssetCall, InboundQueuePalletInstance, Parameters}; use frame_support::{parameter_types, weights::ConstantMultiplier}; use pallet_xcm::EnsureXcm; use parachains_common::{AccountId, Balance}; @@ -30,14 +30,14 @@ use snowbridge_core::AllowSiblingsOnly; use snowbridge_router_primitives::{inbound::MessageToXcm, outbound::EthereumBlobExporter}; use sp_core::H160; use sp_runtime::traits::{ConstU32, ConstU8, Keccak256}; -use system_parachains_constants::polkadot::fee::WeightToFee; +use system_parachains_constants::paseo::fee::WeightToFee; /// Exports message to the Ethereum Gateway contract. pub type SnowbridgeExporter = EthereumBlobExporter< - UniversalLocation, - EthereumNetwork, - snowbridge_pallet_outbound_queue::Pallet, - snowbridge_core::AgentIdOf, + UniversalLocation, + EthereumNetwork, + snowbridge_pallet_outbound_queue::Pallet, + snowbridge_core::AgentIdOf, >; parameter_types! { @@ -46,69 +46,69 @@ parameter_types! { } impl snowbridge_pallet_inbound_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Verifier = snowbridge_pallet_ethereum_client::Pallet; - type Token = Balances; - #[cfg(not(feature = "runtime-benchmarks"))] - type XcmSender = xcm_config::XcmRouter; - #[cfg(feature = "runtime-benchmarks")] - type XcmSender = benchmark_helpers::DoNothingRouter; - type ChannelLookup = EthereumSystem; - type GatewayAddress = EthereumGatewayAddress; - #[cfg(feature = "runtime-benchmarks")] - type Helper = Runtime; - type MessageConverter = MessageToXcm< - CreateAssetCall, - bp_asset_hub_polkadot::CreateForeignAssetDeposit, - InboundQueuePalletInstance, - AccountId, - Balance, - >; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; - type MaxMessageSize = ConstU32<2048>; - type WeightInfo = crate::weights::snowbridge_pallet_inbound_queue::WeightInfo; - type PricingParameters = EthereumSystem; - type AssetTransactor = ::AssetTransactor; + type RuntimeEvent = RuntimeEvent; + type Verifier = snowbridge_pallet_ethereum_client::Pallet; + type Token = Balances; + #[cfg(not(feature = "runtime-benchmarks"))] + type XcmSender = xcm_config::XcmRouter; + #[cfg(feature = "runtime-benchmarks")] + type XcmSender = benchmark_helpers::DoNothingRouter; + type ChannelLookup = EthereumSystem; + type GatewayAddress = EthereumGatewayAddress; + #[cfg(feature = "runtime-benchmarks")] + type Helper = Runtime; + type MessageConverter = MessageToXcm< + CreateAssetCall, + bp_asset_hub_paseo::CreateForeignAssetDeposit, + InboundQueuePalletInstance, + AccountId, + Balance, + >; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type MaxMessageSize = ConstU32<2048>; + type WeightInfo = crate::weights::snowbridge_pallet_inbound_queue::WeightInfo; + type PricingParameters = EthereumSystem; + type AssetTransactor = ::AssetTransactor; } impl snowbridge_pallet_outbound_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Hashing = Keccak256; - type MessageQueue = MessageQueue; - type Decimals = ConstU8<10>; - type MaxMessagePayloadSize = ConstU32<2048>; - type MaxMessagesPerBlock = ConstU32<32>; - type GasMeter = snowbridge_core::outbound::ConstantGasMeter; - type Balance = Balance; - type WeightToFee = WeightToFee; - type WeightInfo = crate::weights::snowbridge_pallet_outbound_queue::WeightInfo; - type PricingParameters = EthereumSystem; - type Channels = EthereumSystem; + type RuntimeEvent = RuntimeEvent; + type Hashing = Keccak256; + type MessageQueue = MessageQueue; + type Decimals = ConstU8<10>; + type MaxMessagePayloadSize = ConstU32<2048>; + type MaxMessagesPerBlock = ConstU32<32>; + type GasMeter = snowbridge_core::outbound::ConstantGasMeter; + type Balance = Balance; + type WeightToFee = WeightToFee; + type WeightInfo = crate::weights::snowbridge_pallet_outbound_queue::WeightInfo; + type PricingParameters = EthereumSystem; + type Channels = EthereumSystem; } #[cfg(not(any(feature = "std", feature = "fast-runtime", feature = "runtime-benchmarks", test)))] parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { genesis: Fork { - version: [0, 0, 0, 0], // 0x00000000 + version: [144, 0, 0, 111], // 0x90000069 epoch: 0, }, altair: Fork { - version: [1, 0, 0, 0], // 0x01000000 - epoch: 74240, + version: [144, 0, 0, 112], // 0x90000070 + epoch: 50, }, bellatrix: Fork { - version: [2, 0, 0, 0], // 0x02000000 - epoch: 144896, + version: [144, 0, 0, 113], // 0x90000071 + epoch: 100, }, capella: Fork { - version: [3, 0, 0, 0], // 0x03000000 - epoch: 194048, + version: [144, 0, 0, 114], // 0x90000072 + epoch: 56832, }, deneb: Fork { - version: [4, 0, 0, 0], // 0x04000000 - epoch: 269568, + version: [144, 0, 0, 115], // 0x90000073 + epoch: 132608, }, }; } @@ -147,83 +147,83 @@ parameter_types! { } impl snowbridge_pallet_ethereum_client::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type MaxExecutionHeadersToKeep = MaxExecutionHeadersToKeep; - type WeightInfo = crate::weights::snowbridge_pallet_ethereum_client::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type ForkVersions = ChainForkVersions; + type MaxExecutionHeadersToKeep = MaxExecutionHeadersToKeep; + type WeightInfo = crate::weights::snowbridge_pallet_ethereum_client::WeightInfo; } impl snowbridge_pallet_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OutboundQueue = EthereumOutboundQueue; - type SiblingOrigin = EnsureXcm; - type AgentIdOf = snowbridge_core::AgentIdOf; - type TreasuryAccount = RelayTreasuryPalletAccount; - type Token = Balances; - type WeightInfo = crate::weights::snowbridge_pallet_system::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type Helper = Runtime; - type DefaultPricingParameters = Parameters; - type InboundDeliveryCost = EthereumInboundQueue; + type RuntimeEvent = RuntimeEvent; + type OutboundQueue = EthereumOutboundQueue; + type SiblingOrigin = EnsureXcm; + type AgentIdOf = snowbridge_core::AgentIdOf; + type TreasuryAccount = RelayTreasuryPalletAccount; + type Token = Balances; + type WeightInfo = crate::weights::snowbridge_pallet_system::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type Helper = Runtime; + type DefaultPricingParameters = Parameters; + type InboundDeliveryCost = EthereumInboundQueue; } #[cfg(feature = "runtime-benchmarks")] pub mod benchmark_helpers { - use super::{EthereumGatewayAddress, RelayTreasuryPalletAccount, Runtime}; - use crate::{Balances, EthereumBeaconClient, ExistentialDeposit, RuntimeOrigin}; - use codec::Encode; - use frame_support::traits::fungible; - use hex_literal::hex; - use snowbridge_beacon_primitives::CompactExecutionHeader; - use snowbridge_pallet_inbound_queue::BenchmarkHelper; - use sp_core::H256; - use xcm::latest::{Assets, Location, SendError, SendResult, SendXcm, Xcm, XcmHash}; - - impl BenchmarkHelper for Runtime { - fn initialize_storage(block_hash: H256, header: CompactExecutionHeader) { - EthereumBeaconClient::store_execution_header(block_hash, header, 0, H256::default()); - EthereumGatewayAddress::set(&hex!["EDa338E4dC46038493b885327842fD3E301CaB39"].into()); - } - } - - pub struct DoNothingRouter; - impl SendXcm for DoNothingRouter { - type Ticket = Xcm<()>; - - fn validate( - _dest: &mut Option, - xcm: &mut Option>, - ) -> SendResult { - Ok((xcm.clone().unwrap(), Assets::new())) - } - fn deliver(xcm: Xcm<()>) -> Result { - let hash = xcm.using_encoded(sp_io::hashing::blake2_256); - Ok(hash) - } - } - - impl snowbridge_pallet_system::BenchmarkHelper for Runtime { - fn make_xcm_origin(location: Location) -> RuntimeOrigin { - // Drip ED to the `TreasuryAccount` - >::set_balance( - &RelayTreasuryPalletAccount::get(), - ExistentialDeposit::get(), - ); - - RuntimeOrigin::from(pallet_xcm::Origin::Xcm(location)) - } - } + use super::{EthereumGatewayAddress, RelayTreasuryPalletAccount, Runtime}; + use crate::{Balances, EthereumBeaconClient, ExistentialDeposit, RuntimeOrigin}; + use codec::Encode; + use frame_support::traits::fungible; + use hex_literal::hex; + use snowbridge_beacon_primitives::CompactExecutionHeader; + use snowbridge_pallet_inbound_queue::BenchmarkHelper; + use sp_core::H256; + use xcm::latest::{Assets, Location, SendError, SendResult, SendXcm, Xcm, XcmHash}; + + impl BenchmarkHelper for Runtime { + fn initialize_storage(block_hash: H256, header: CompactExecutionHeader) { + EthereumBeaconClient::store_execution_header(block_hash, header, 0, H256::default()); + EthereumGatewayAddress::set(&hex!["EDa338E4dC46038493b885327842fD3E301CaB39"].into()); + } + } + + pub struct DoNothingRouter; + impl SendXcm for DoNothingRouter { + type Ticket = Xcm<()>; + + fn validate( + _dest: &mut Option, + xcm: &mut Option>, + ) -> SendResult { + Ok((xcm.clone().unwrap(), Assets::new())) + } + fn deliver(xcm: Xcm<()>) -> Result { + let hash = xcm.using_encoded(sp_io::hashing::blake2_256); + Ok(hash) + } + } + + impl snowbridge_pallet_system::BenchmarkHelper for Runtime { + fn make_xcm_origin(location: Location) -> RuntimeOrigin { + // Drip ED to the `TreasuryAccount` + >::set_balance( + &RelayTreasuryPalletAccount::get(), + ExistentialDeposit::get(), + ); + + RuntimeOrigin::from(pallet_xcm::Origin::Xcm(location)) + } + } } #[cfg(test)] mod tests { - use super::*; - - #[test] - fn bridge_hub_inbound_queue_pallet_index_is_correct() { - assert_eq!( - InboundQueuePalletInstance::get(), - ::index() as u8 - ); - } + use super::*; + + #[test] + fn bridge_hub_inbound_queue_pallet_index_is_correct() { + assert_eq!( + InboundQueuePalletInstance::get(), + ::index() as u8 + ); + } } diff --git a/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_unstuck.rs b/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_unstuck.rs deleted file mode 100644 index 1b00e18..0000000 --- a/system-parachains/bridge-hub-paseo/src/bridge_to_ethereum_unstuck.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Cumulus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Cumulus. If not, see . - -use crate::{weights, weights::RocksDbWeight, Runtime}; -use codec::Decode; -use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; -use hex_literal::hex; -use snowbridge_core::RingBufferMap; -use snowbridge_pallet_ethereum_client::{ - types::{CheckpointUpdate, FinalizedBeaconStateBuffer, SyncCommitteePrepared}, - CurrentSyncCommittee, InitialCheckpointRoot, LatestExecutionState, LatestFinalizedBlockRoot, - NextSyncCommittee, WeightInfo, -}; -use sp_std::boxed::Box; - -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; -#[cfg(feature = "try-runtime")] -use sp_std::prelude::*; - -const LOG_TARGET: &str = "runtime::snowbridge::migration"; - -/// Last successful imported beacon header -const LAST_IMPORTED_BEACON_HEADER: [u8; 32] = - hex!("8ea383d85a87a2e27b088571aaf219231c1f6b3510d7be3c160eb1bd93dacc25"); - -const NEW_CHECKPOINT: [u8; 25122] = hex![ - "80c58a00000000009cde110000000000f118ba039276d46ba87cd50790e2547060aa6cd260476bdb499dc38ef834d618910884d25c9608dfe669a39ae64814db99553d82cd7a5bf5808240d2dbef04e6035075425a8cfe9d2bc194fa1ce245681e84909e4159e0c5cc1be7f876ff57d0af821d9b65aecbfd133c02eeecf2d8f64a164474274529f0a0fa9f8ab033cddc183b5dc028ccbc6c27887cbd65da8d4b8d6983ebcf4a910e6e2403b68f52628fb555e3486e21fd446483ed9df35377b07851e0e07803b7af34cc02494fe7a71fb32ec66a1c279dfa9e12b96b4a1e44fd1d3ca5db007ab2b953f6708514bc65ea545ad562b10a900bf3d9b25b5153d552ac07a256fe4f7761a5f9fe130c8e65b8f35ec53499db3a67c630148b7baf1ae8b79c00ed0c5f8f808bcb9e01cdeb963d8a6319e82af0f8a64b1819e2b21ddd3b07b74c8ef2bf01450a4bcb4180795b745f2f11c449223cb5590c155b284ef45ca108dd0c6e2ebeeb1e93bf710e1573e1cf7d2e3ce4c45cd5e5cc6aabfb110fc1c748b6a22677b333aa36d283f3d99eb09577cbd44b3fe69dea5d5651887877aac4f7f7eb0856e272144e187aeb92df3bc4b789b16ccc3b9f014b60b56159692db7f9ec5f2bbf753c0e19a5a22400b614c45da5ee07ff2a4558c2038f3772f2da1772070d65ecf063b908ad751a192cf1aafe980d1b628aff8bb34f7cead01aa4baf5d8be084e112f2cad65561c40a0932cbda6d5d37d6650500f14b7269575e1ac157dae537eab19abb957f40043c71954cde60e164200f453233a8b77fcf8ffe5d95463b486da0e6e873a1a00d3b04aa4f0672ad6b6d03180cc0a089adcf50b7e3688c68b47d1d5812972cfd5952b4197c414bfad6025d8c8f060f16edcf8ba8bb9075672310a1e10745e4e90fbbbc61f2fcecf5399045b103317086f544bef7b5414e373401b13893a7520fe0201de90c58991af476a86d9eec14cfd0baaad4278204b6d822cd32414da207ec86da840cefe31c5cbfa6ceff0546294c296e6aa5683093bf0a69ba502c89e50a6084b899a36f3d60db2dc9ba128210c4e75d76e83799132cbd4fdd9fd17eb704703cea9df391c83d66a2d7ab894cb5a15a575d1e71389b8c57d63ea48017254c02c106c64b3e8aa0c2f33b9af3ebc44e541aca5e69cfae22549ee562eb8e825d81830317e565d04563ed05fb8682f1ff79e0c855990e03a9d18ad8ce8983fc55deb5398b333a26db57d0e690ef6ad56d85512859d9bea389877d01d3fd8ce1a0517c87ca515b12ac524c47439b2c4c00b553f8a9a6831fccd0641f8eb33c0eeba8cb5ed88e035f5bfa079644258f5077483b45589d5cf4b53915bdab34d4030dfa8ad85af76e194db58d453df3411431cbbd8dd19e619ff613cc3cc9e88745bd1b3d24422d3dd4ebd82467bd232600401a39fa3134a2cc099b690158e52694b2141ce2979ee84416d8c89f55c23cfab2804e26fa2f58e96fa9d8e7f7fa8c33022247ca0cd1808fbccfa4f3dc4e70ed62e031598f4776745fee59bf0fd5369246ad97c2f2798e808fccf295ce5f8ad8e7e70268d6667508104ed10beb70a794196a3b7c7e7188e766d9a68d32ba7297f9f916e7e20f5afe0a758dcd16953dd81ed2ef48f4d8bc8190f601dd3da1df6f78ded9ced42b00a310957f65ae029e7e170d106e9593dc2df9b54d9d6692ab68e9d42688304fe8257fdade19bca9d162c83b3bac4b6626979a8fc77f49105f49103d55374bdf18e1638be1d8db2945dce2a9b7ca3c772605f9059f0754a06cd170268ed71a19419ec3c88bacb63bed8086c29322bf2d5ede197f3dc626dc83fcf7d3ad2aa959d28c9f659824abd2e7392a2658f1cda46be4fccca644292573c21ba76cd183817fe7d59641bb39a369f4b43237eb752ee6e0647a94c0cd1ee669010a851f133e7d674bf23e6ba23028bfcf6ead7d960833ddf004e335b83ee062938bf9183c99d97a411ee79b18725de81a5131e8c8f0e5dcac8837d036ed9c85cc02314994d865c8476e63100deeb615722ad6f8110b209ba9eff76fbcbff25b1d83f31e7439c00ba009d8ec4f87d32ed566e7f516e7dd48d085808641df325942b46d98b616d8bf622147f24e180a6be27fb74e042439e19ab3c73f833439a86dbbcd4e0ac43db4b891b67155ddb007d2475fbb070e847fa254273b63d0bad326ba60dd8c0849725be0496d270c2cb30804da546d94b3071e6de53a2ccd167acaa2439920e9c77e475fc120a12d91be2176a87f6c7f57061fba362e5c38ebd01f01c659c3631bccfd6973d68beecc3b363ba5ea9fe3918cc7629672fda8922852fdae18a99ca7536861c73a6f241440fb9116ffb3c9144d649d00255a4f15b1f6afa5c88e59885eae06fa271e0e1ab7b5a1b4ce2827d3e2cb309ae2d58e98a926d2ed525a8e8e1d4bb55f621eb6f688ba7184688819bc8aa9e95b114b78584247ab2f7e8c217ca0de8e219646f9c0184d03f292bb3138feebdd38de30ba4951cb1665a81994db24b5105ddd683075f6cf5f884ce7ee6525dcb09e04903424d7b8610a4be604a89d099d71d038091eca1a6317291e4fdbd84837621ae37182bb9eedc4182c1b3e3af35491cfa701ae2f55522c2042e7d8a93a54c2f505b62a748e1377789780f6fd9c54981e93f76b65a7c0010ce6f84bf03154c2d75b1da316b9dc62a2f62736944cb935f2f985da9f6fac23ea4d578136a1b3cd1ad29818cd02e9a72da1779f07c7a9f88b4e9fef6ae1db26de2946ba6edaa1b43fcb1c7e10ad49b9d84d060c6ffe0ee4f2fdcc34d27601a6bb3fc326b7dd600aed38ebdb605282d7346c990194aa7bc8775a1dd5f64c61abe8b375d61223917fc8427e659d431a27391ea0df523a25e96210e17ca85cf5a4f5f6fb6b5c4473b4b92c62609bf31e8bf8402e391e3a7ae63d4aff55a17ac1d97620b97983e3ca421a81ab97f811921df29e09948dddb325945e3a7c53fd68c9c9633321afd3873ce4ebb4a6856b4a4caf2e57a2e2532a20bd768404e84d2b2044b22f9b2e8f76946029db8b84290f6ed94df22c8596dd9c6bce3cdaadb43bc90d1f263e64bc00863fa218495994cd4b42025b22d257d3ab275ca382ee10231e8850ada2b50d0fd507b34c0b74b13d1794ea68c1d594d221ef84f9557bb43495f9652e3fdee490cd327116aba0bde4812a95c47955ea446dd6548aac044e14798beccee03b10a59ea6d9a5a2bf6e6bba2f2130128a29ead57203869d1fff9467d835cf8e7ad3f3d2fc077dfe11769982b2fa5e94379c3a2087edf3bc587d27987811204505bd74d8ef13acbec609ae24793f5a2b101eca199dcfaa4531a987b6524018fbe4c9ffc95985096a67bb041c37056498dc3733b5be3d6d03a001b418ab4c0ef72c609ff263136e14c16e9ffcc8a2c6ab4b3b1bb730feec0a1ae7c15fed5509ddef0e00b8de4dcfdb93be4e6ac902462ae732c20a79209499b9b87870e0476d016889a60ed361c5353020a3ec98e34e63b9f3182ac02fe66da7efbb1a3895c727cdca56fd43edd20bff709ce5f86fe5f9c880c11ec739b9485c0132efeca6f6014be637028ec04a36b57345d5680ca76837e1aa7f14999c928578daf668cea7358c4110d88abfbe25380352feba160638608ae27c8336fc4fccccf4eb0abe8942f11a77c6a39786aa8287ecff1af4732e63c834f325d0719e5870914a7ee8cd22592c42b6bbe86ece668f7b75ab921fb30979ea979d9a67dc6cd4b3ae2cb3751b35f51c7c8fcd75505d656d10fd54bb1afa2d24afe1502740275589f07b5371914d703690da14b54285e8943f0e6c532a977f5fc3c1564048b19d731cba84f69c076a823353ce020094fb46c5784c2098313f99c96c539258b59630de96d217795318faa7bbdc52aa37525c7091c8574c4a9a03b5cbf80963facc40ea68ec48cc24f71f3337c8f7871aea9a18aed2b1664c9c5f5af76dec55f74bb441abc21da357de621473325018aecc06917aff025087275ca4f964b8cd945c7c41964fea49386cb3ed22036e0474cc2def65a6a380f9a120e5560722b942f5b88369817d0a965d6482ab324b7af23bbf854a41fc2510c2898712f6177f9990a2587a2fc9d2cc0b7ff3c07b5ed0ea20c24bbaf58d5a29ab1c64f42e8d94ba4400c65a90a6ea0a7d2623dca1b2e4f74a4374faef87e0a77b09a1b45558a9b81b9402b933317fce57824dca4b911f066892672e667f37ad0a750e09802784f2a0f6ca3a675b5f6a6e76e96ed60a36cb09046b39975f8575adf33e2b0ec9eea1cc61ec6364a0ebae32e9902129aa3b174c0332bd338a33dd91cd8159b47b10883b32a4ba60759c14f12b8741582bce5cfa0f7d86743e0da364170d9677cf448d7fa3590256ea01dcf11905726b88b15056236d8b65ea63039efd66b7fb4f168e6ff46fc5f7d7dc734d2d406153340788216a5df6ec9fa169ac78540cedd4fd9a00382798ed054223ebbac19c32a0e02b9a27c5db531e507c1855fcb354bea4e484bb30bef99bcd63be47e4d3d4a4e0249f41588a18519584d6086e0b2039b5d14130a4b6aa53a088e98ac24da38b83b8f1801b612370c71613612bae8e5f1ec6e07260fa081bacbefc947bd612ab85eafe775db1aac43fd4abefc58d49aacb57307b29ac2ba517af4e7b26d6a836338d6c8941db0bbb9ea279d33bdb9632be5ffd687acd2b9003040d346aa947425b475d04333b54958b6f4600f7d7456050f160e2a078302e7011c634abff5e0dc08880d5cf6ec705f94951273125ee1886396fd14df2ebb8f39e6171876ad7eb0797e97facf88217ecb60eda8fb336efd13715928f1311606187e38e0d7a4cc94d9a1a0c36aca43f3a98440724e8704b935fb52a0d9aeb1b8861c6a7c4535af798f2d46a769f897bceceaf1f5fb55986a40567a8d13731b4274787ac1995b77d08d780fe788b45ac80dc136504f7e1f8a96f55add4bc347ebcadac13dc5f43436192b7ef765a23dd8a82083dafd346a8ed35890a855a0856abe09f943f27d2ae609efb77499ed7fbac5f5d6ebb58bc1aa061fe70397143434f1b318e3d9aa8f5daa5543f7af91f534d2193d7a09097c373ebbcd9982c24bb1ef2c3b6125466ed13ecf5776c032a3bdd2a77107d6a1323fed662ee74a8650bcf27ba22e9c5172c069b0db13a03a0aa7e689a0c6cccd03b894348e2b88a577921a1934a3888a13c4219057df4393158c7202ed74ba8ccce6491af1b143758cc25e4261cac346a38761c0a6a24f275e1fbb117e9fe566a555e86ec79072ab3e3c17471bd6fd429af98b00b8abe4cbb397660351dcdd941bd3c8b6f77ba9a6f7bfce57d1820273a8000b9a9cc23fb8536bdac8a3f780f0ad86964828ea9be5595640b4a7a6c14427d7cde445d1fa4985a032beaaa5ad2d47bf2a536f25fd855247c5e229f5084f4d3edce308fc0e3e92c00ce3ea6b6c81381cab6d769c81410b76120343202a0fe78b083c4b3da0a5a16d4169cbe2f18fd611cff69d75673dbb01dc2e288335644825e3297a6b94ef4407036fc2c15109ac307d8c83ab4d8029afd1213fc4c2df73da3eb545c6c55cdc003bbf6bd302c8a792263c2ffb1acff931957e761bd98ada159b91c5db7db9cc5708843bb0ff18b82d85d51f9227de4a5292d4cad152bee03e97007f40dff61b9f326121e4d533322a8a04cc5421aa4fbc8256bd21c37943bc25be49e8ada61e5f240c754dae5fb242b5f4e101317143d0f7da29a42dc81dac6987517ff085cc9b2eaf258fc97aba502d83e38247f5ed56a7eaacc68f850b3541a435304344f3b466925cdc531d54ea55988271c18f993ff6ac2f02a4c1f1aeedda7c20082dd5a7c2291e1ee60a449a6b8f66f2938af7b48a2ba01b453cc2d98baa4bb2449139c3cd4436daae2c1f637c8f7fee6e3897534250f313ddd3417bc92b0129c347c648d7773c79655b4aec68623b2924aee7da53e8ba56772cd6520a5c6d78b553627f3de75b056bc618ecb17a94b4d6b60a7164b024a693e526bb32e97f612b92e6a798b10b774f3cc7886a3bf419c0562801baa67fb28b3c02909bca1d542cd6da0f359d6a89aa73760b8d3642e3e688294ccf604369978ae4c9b220a9661205ba7a1fec3e96e2e10d73af9af284d7218dc9c249c6fd5f339ceb3380cea7f5b9ca305c04d9f0322c827bfd5ff8704d9a0b95c10ef7a4e3a332ac2e227beab26f367fd5a61ecdc228c73455890e935d949dfaa52ca8e65dfd5be9d73c4be0f8d2c0666c688de7e98de4f567627d3aedee8eb7fc75c4ab573e3fbdc7adf0d934a25d5312c8ff2cebb7959177aa440fb3a7cc8f4b85dbda4c65524df016c7e77ef90b11038e6da568d6c04bec1d53740d8d0e669d7a7f9ac3e979e816194cbdc54ae7fdee3d793a0006d415e048fe4e0f3f69c04bde7bf192686e53f7783fe7caaeee6019ceec793e54f3d0ec024e9feae6f643b8826dee65647b9f53a51509d36464685f44e1964eafb98b825d53ee3a8e9f85894ad6097a5cefe8daf6931ea7033400c7808d6be6cbbd244a6a694ec9bb3602a1bffaeeb3ac266ee3dafb4a0b8af48486c8c682e70597d5952e78a5fb01137dde04b8dc0af662de6b8a33a890f40e3c68c1c49dba60fa5e7e9d8d1414a36b0394acb7549bdd405732d118ce9e18899f897ada4be16a73a5d2f8e83b36d1370e0d71a3f0b1ab6e956ae959fd878374a31d52c8f6a5a30442652760c9de032cd6e1f621cd557b802777f290fa716771bd240f23217c2993a56aff4205f5b233e4403d73c719b6c483c0ee81c51056125793efd502e3b7be54138357335f7ed5370be3baf470ed7287a0da23815690ccd6d59c55ae1b272d46d2d57d7186e8b2550350b023b09cf34947fa86f24ca0b8b71a3ae3933cf8aa43afc46d87de82b57b3fa83e09e87ac43e362625ffddc02d4bf35f1514f755ebae9aea374dc7720319d4f80d4c9609d0970f16ab5b6ab96d10040777e2ba8dcac635a9358e636fe84a4c9794ee9f7c9e6b4682a4c9ec5b2a594071eb34a5c581d1288678dac0b525b459f96f377ba56a1eb1ae9275d70d33c3d4741e66144ea92f880fb154ce6d5dd8fc74fba41d12e9d66c859a8cb892df9a8d9398a80fd1a746ed19cda457c58fac722259a67573b7add86ce157cb3fd1e01c077e93a1560b2ff3c79c4cca88100a4cbd6e0a40fa3631d1de6e035bc197ab7573f10eddcca678433f231dd23ec2fe50652473af6133bc8c1033953baea90012e2878afa07e842f8b47a328ca9df0d21b58ace0fa8e7e501a5b03313764c81e2786e9489fdfe741521bd4fe299548e89bab19e8847ab274d0273f70f52e71e9003d42a7276521750e5c0792ee01cea2be884920f52075dcd02e9e25c8307dd499764fc029717c2ae5178607d17a730978a8896b6bb3b97b47cac98aba15ab24e1bfbefc5a2f8e2ac0c4eef44b26917de5e7d8b7330fca531689569fbe31003b760c6f4bf17460eb51d21c11b4cb8ac3bb28ba7e0c16d35104d92b1738e84b31cd27408d095984d8d0b20e0386e4e4670f34d0e8a0314500df98a568303486dac06ee4c6b14e1747062c34af8ae21b715a30e4654806717a334660155b8ef0d713e7cd2d0ab0386016b90eaaf8468e75bdedb81aa9f3467a86e012916afc5ed65ee4542016b22a6926c58962decf0319b73397e000a8ac83245564e5ba5adae8e0c76eb64bc4a82e05f9b376185aa44aa9ae831f3b2338badaff0436c57c38e9f3242aa9c9f7c00807a9ac8a97ed812c5ca69767766f87ab3711cfd478f6f60f9218c32a1c5d9d7b5bac1c1093b399c46f3270e26f035fee1e5b2c9680298b570a2db6fc8f2ed1c5b9eb65c8b915378db43893c9f4ad7026c4867f04e286d26c70e52fbfbd0420c4fddc0179675d2b2a5b7a7a3bc325967566662192b93e1fbec87f90e4861809e84e5a691bb1aed7b03797036c668fd07aea5d5586d1ed72df9fce56a6c599bff50a70086e689fe0d102e078358e4ebcf70746e7b86ba97ef46eda5927fcc5bd63564794ba207b1d85a2b38ec7a93e84768962ac23cadd9e4d66daf8f9772ffdf311a1d28fcd2187b8a5f83b03c64dc49660f630303ca5d8e37e4169dfdbddf490dd8f226b29774d95082314ff6112ae77869e72886c7a93bee730897b7d38ceb673d4030283a248b66c62c9554e3236655486c214baed7631a301fe780d283adb6fede12e43e848f81f16b36f97149263fa6bf54484c201f51665e2532f6b29d4037a19bb798d5d73aba460e78794afd7f3dc2efe998eacc597a27ae8c7d0378a6aa42dbbd2606b9a9f0045adc22ca004ac27a7e0b87d282c2102797566e215a456cd34e754c67258a067db1a6af16ee8dd50a863da3939ea8f26e89c5e87c3a35dfbe08a98c0f2a45b297609ae574173d9cd07955814ba24fd0810b686a6a6487a34bdadb76cbe8d7a100e29eb66a4d2ab72df6738d15092f519d8cd1ff5724e359d2cebc2ace815c4c11012aefe433e176b394315c6ff6b31d745b65de56fd842c78de07a1b22652fcd11a340caaf56626a999625d32d762c81e097f4d548d94eb075849beeed2d57c40ff9a545371ce9bd9f42caea334101a01afb0a73bfce8fa0c6ba88e9c159f8009701773f2b9d79f48bb793c04fedf8278efc1a54c1f77a1f8ac4e83e784054e76160e05af8b06e565a5eef9b06e5623f5c0dca6f2c741de8e71241d94055e0115056200cc5a5de25c4cc3a7507e3b153bddcd89bbd9faa0e13c30c6aa4f3b8b28e7436b0564625c15e7425ca2e1dfcdab8a721d5a01314e23358e991ae4eaee313c8efe723b19a22ea8f857667afd92267cca94bc82d6bd73f4a935c2f32d79dbff17f9e54b463911d81d80b3c9d98d45e7a93c3b6198ea8b8223f2223950196950dcd4f5f4d81423d61c682c040b2748e57dd3e51b207b4bb1658fa013f1f6ffcffb5a3df119753e65619a5dca4e507f510360721e37654b76771814fba673e1c8ef24ebcf91f2f7d08db30da1a1b0bf3300a66d992072f15daddfb5d08a08942f14e854dc29c3029f6c27968118aa2d23b528148a6e70f2438faacb3c4ce494dbeef03508206826ca8b0bada57796f4a4cace53a1339b41331dae0c6cd3f620ec58d04dfdb03d0710da8cbc876ba222b16ede82ec4f8839d42d8d92f4e67f804baf44790c00918f7e231d6b79016cccdb2efeb7858e1e9e4a1eaa67ce4bb608790b09894b06bd0803684ef706c0ccdea713ea7ee376d9d6c9f676efecc91ea317cccfebfe465edf03278410fb011e5fbf8d50192e98bc0f65aa4a8615e44660d3e047e2703d60f7a6d08d468611fc0b1a0f16d3293842c80a3fa7de450ef0ae47a084763780da1d7e9755b80fbb07ec7304d1c19a7f6dd3c2878ecbeb46706d9939922b92b3390dd918a11eedccee7188a65503c983b8804acec6bced9dfccde579891a1a884a4000adb864d8f9be54657d653713184a81225a83f314b07e32fad554ae49697d5cd9927761fb78eae1e8571efffc50072b44a3d229e07cd8cc57751a33537e66ddd2e4950793b39d471821a8bb26943e0307d924e82d3adb7fb04dfbbc1b1b832643d84362f465a8ba7bb8543ab793caea761c9986b845aa2ae3d99604185bc12c25019d5a981812348c662cae1795aacd0eea8609ea2dfaa0e772e9aea92d2d654305ab6a0068ad1475fe14f733483b03e768562e563739a412f4d3eff2ae6c19883681e3b22432943b32d9ebc6941674deb3920c52624605ad196bf1f8146689872672ddba241100425d7b73d8ce99f141de338f94e3e6e1a9bd8d6ccc8dc87e585ea8120121308ab58517549e87e8d9e358f7c653af923c2b56a0ab756afa52c2fc5b1133407ff0d088914f04adde7d8b9a840156135b5991dff05165e34974d92702d93d7027d56a6fe2a9004c05446ccb7283f2994cc064cbe6850dc82c9865738e9ee7bd205a50ae83128f007bb1b6e5f330fdb634e823fbb09c279609e9819df52bfd3214635c80c4fcfd47672cd7dcb05a7ffe0bb71867e7061764cb68fed668b00335d6d011be76c3545c4ffb3d54810fae5c498a29ead7fbf6d0c4e707308ad95103f9b9bcfd3e3a66c8cc66e506a650a9a2f55de7724254943e076a0aae77969219f0df9f7781278b9a7cf9960fb6ec69d05e819b3b448910a59f1eb3307135b469dce550594709cd9bd7e2ae8defb1526dba97db70b04c2d361f468a3193fd57d0fd328117d05bbbfed2a6d3ae4a555c332dc38fd74daaa6a8b3b55624836e41d8aad26be0982de48a98f93153b27ccb597b8f68f798789a9d46d84cb72ef3cebc064e428613757eb75c86f535b3dfb13f7abb8bd9216e70f04c67da84b6d684ba7bccc57b5d4b67aec5a1ccfa2c858017c579cbed366c29b6cd1ce009d5879ffba0c650dc18e683b9610e651584b9a04a9fd73cde3a56904b09f6ae9f6a4bdcb0bab6c1e5b8e7e0eb5c8bc1d130cea0f4a6be6e364a28021fa476893e87e779022b6cf983dcb394fa936a2245cedf379642716df1a932d899e56a9d42ac668e783a910fa39284ec7ab00f08918acf9119f9e964cfea71404064417aa574c0416acfdbadca8ba43895bfff699cedc1603f781b4b7c353724019562a947afc7e7c30ffe6d9857346aaee04143e19d8429e486003243387444b718ddf52bf372f542a95e1280c4a54299d13e3879b8e479925aaa84368b47a69f9c1fe7598f0d0f5fa405ef3829299e970a8822e1885aa33e7eb400d538d335ab97b746bca8da82350e3d52a9833f010d9b998af92b54a67f6d906d12fdf22d64db5902452071bfc8fa65fa010d2a8ec2a1b8f3f38fe4c37fc95cdc46a8ccb9743534278d225a5ce233a15d503158e1db6e9d016db93b240aba04afdd7ed2f8f909f32d478b149569b768c13c4f9f7bc14fd5da12bec4692dd6119bb35693bc0ba09cca16c496164bf598d24e5fa641ca59d4b283a60b2a3d30f365014f6c8d79f0b3d878a5cff8f0ef98e48b5864c9e0a450fcc3467e19a3761ff916ff1e2a89f61bb73080cab649a91ad197fa3c3b17c6859b57f49a845fadf994fd36f575724226e32866725d8f641bbf052bcb41c96c6b7dfbb13324b10a801ae1314373b77b6cfc61580c46bfaef27b0b0446801d054be7f1e33266bbc267c09c6aba0c3b81ad54da83c0b627503d9462b75249569c8b97b6da662c18e2269b37ae6eb3e07e995d92466a990b3f8856bbe83a478a7f8725b49285b479e1cb89335af647463a4892216851668daeaadaffb0bb37d8dd651c509c3743274eaf7a2a51a0e1777fd21ef8a1555f625d5f21823aaf317e36369bd5c4976ff3c848256df750c421c9145f64a59a62218ae70d4684935b63ac3ff6f4a96aeb2910993aa02dffa434ee1ce52cc899089eac0c142a6d2ff99cec8107649c42b61a32e9e4b0541635191007ba47803c1c351ff2302104f39c4d5dd1614175cef07ca15cbd0a774dfbb79e897bcce54c4f49124d0abb171159eed866101f8bc4782c167ad4332e04d659c071fc7cfa8530854f8e6e93f21bc8152e672ee134b93e64eebe550f35e53691d1ea6993ad2158006191f1e2973efc194ca0ab66fc174758f0226dc531fb265a560e5e38a4225c01b2bc362af73af9cf446491578ecfd176663c471c60a613ad7a119659ee68c43a5a08cc7c737c58447668644f2444fdd978bda86c60bbfabd0098e7d29746440da19e9ec5c8cba161f299fb9a5a83ffe05ef8433746c7eb6e174b4f245bdd63973c76c73befd9b7230fc8f115813e6651f1cc7445c5622af346dacd00bd0d6d47f204caa07f54d4c8c3a6a1ffccf161038bb7e2184821427e2bc8fe3c8cfddd731c8d98b4e6386d70a6d9040a8a4993061e72773d1a82dadc8c9e0d0927d990916ecc59118eacb586294277fc8f63de585929d522e13f8e27331a96499ff0f1daa43e30176853767fa3362209f69dd13004e6e6f7e898182dcbd2c1cea23b682caf8d9139d4f0baa12592284c3569031f77d4cb3df039991d2d032f5fc61b035a0eb2f70f7cf1177be908cb8eaea47baccaa254a1533cf91f52c586e5648d1271cefe9633f39cdfce209e09530056123ddafaae6c8cf7cdc4a5ee592ba291292adaff17a97ed3de2ee575af0ed4b4705c90b30f42902f7f5591aebc1e5e9a25b103c16aadbae2682df90eddca8610025bcd0254fc55833850ce6b1121defec4a9e502ec46af0293dd87f90fabe7e8eb0d758cf4a6c2c6b4ea6bd2183ba734471c82f41105179d222f34b40dc1df7d4370be2d0b1c985ced4311a85479e7d5b520fad7ad6a30fdf272f3c6140487ce28a9b490c65e3976f35e51d1e5d3147a1fc418c8fb9b98dbb032af3193f1196689423632d92fa81302e998faa9b9964d0a92a7159bfb362749ae88dfcdbb7e3b87ea009a4fa76880b817aa55df06b1d2327b01c387a0b926d8ba31a32a3696402c64e0a02efbfc32af918129a4e2184833c3a763c9681092db63fa29ff811de4fb7f34211d7a05c5d46a890e5e058b18522565e89649c9e397b3c4a2a35065fc996469416425e3e59cf69fb886b9f89785c9c4bdd8c4c224bb826c0c2fe2928a66d78432d240c1aadee7acc061727d3ca44db2ba819cd401cb9404751d1f48f23184f3aca22245791be2ffe23c25a811adae614effe498d6f0c5cb0d2cdc6714b3f23a1c7858ffd43dc1d1be0f760cf28d2d3e64d6310854d6d54471d71e8a8d7f77f3098378ba1e5122eabbe0cb9d224ed4904429b2b275f5bdc45bd8eb71f9d243e5b7e55161ff23e35434e83cb38c3873c037f255995350869d8c06ddb813aef18bdafd7a280d92f25b5719a242000ebf0a89ca4589894f6aaf04e0288534f83560c53c82e472ae8ce54c5dd9812a6964174192b857f8144a77af9c6a86d4d301212ea8137352c14a002fbfcfa6c56d4df69fc9c235ae58b7fb11df3bfc2f087a051095beb722f58d1d1c6b644f989ebaf4bdf648b8addcc90ce1d8d080acd5ca2e6499bdac856177d8b121b77e7998ed394b47a5e6badbedb0e63207d84190b721b7a40037df1bcf45bfee6c953aa2dd319498200365a5518ef7815c71bdc88c1d8c317d9c1174c401cec7eef84e49fd2e13b60210d58cece2b3ef17b0fc0253c68c125cc18e028311623ba3f0ed6126e71e0af814fb5137bd5653b6fd923ce03df31addb6728df0932d710f876b87e4ec88b05fc406b2cb5ebf3a7097068a0a3edf583d44f7a52e042fecb083bc6bf8927b503fe23134d1fca2d7238e894606860ac772a3d371643acac90dd864107a046dcace6e1089135612040ed33ca50ccd15358813ea65077abf2da58b84891ecebd6856ec6da84e1aa05007db848d95b27246565d7fa46b2f4515fa38c33b0c190b343ac27e18779082eed3a54eb129c4e889f52779cfebf26b915227724e16bad10f4a2037128bc44c341f90418332f8037c34cf4e781a01bb9421922b747ac89ab2a8a3378709ed1c401e8445c2272d26ebd9b585127fb57d5d183e52b2e17861336cf9e10e34073a97a4880794a507bdc3c9dc553735787357eb8f726cd7ac0b56559fdbb1e3758ac97fda1c37419da24450c62eb6dad5e479608bbd4ed4296c6ebf812b6a57c379c796a5a6baa3045f715c0a7894427d314ef37f454c83cc888b165aca2a3eae11a768834b6b358bd399fed1dd302fd79ebf951527a448669c516cc2d0f63f7f968d138c3af179d42f02d3c0f627eb7dae2f4489baec3626c85116dc23072b4d9c59f35564137816b4ff91fa4988cca72f0583ccf80a5ce91edb8642758f49118ddd7cb598f92cde96e8cc7873c34c1d50988346307c7ad359a5fb1e2a8f21b54fc1f800d83a5db56f7d3c459500429346de68a1a049a610c86dcc5a7dd737a0b1525791d8712d4de313bf3e68fca59a38a43145074bd0235a4e599da5f58197d353bfa8c9432c709eb3a6a8b533930531b16388e0d9df67c46dd2199188be257c065c55091a1006ee6f8f93677f3f9ba7a7e0989b993fdd53a97b92b7a33d4ab0cda47ed4a26bb9e6f0ce3ce05f9cc563231e020fb655e76ac7276febba742c99f5928f17c2f5788f0f9bb4c3021dfcbe7b86cd1396aac2828455064d7cd2c56cab823e2e1b56e6f41db25ace49d092eddbb0913c13f9c8783bf986e7de6fc5f2db09ca04c6837730c7ecaed255c6147b6974a29fdd2e3b7140e3397fee402c9d478d879aeabb03f0f3362f5b5a2ee4d8b92aa97a0dc8c8465d0375d8e0eb3db05589a86dea8ee32ba2b040048f0ec7ed391691a1cf93c439737fee4445fc2750378f3c3dcef47310dee2ec95558e2fdcd69fbe4eed7fb4f804970c4afb7ea2f54486a6122bb870abac18656546f92efc00660503ed2ed25be1b43275cb454bf1cefe62865830ae736357dee7eb125ac93a308a7144662371d634c3ec003aca83647443cac5f8e8a324d2a8ff69722da02fdaf0f1ddcfbf836411cd5994f0c8f816fc8e5a738d6778d4afadbefd3eb830ca2168a1cd941d037f8f0889dcdbc7321b131c7bd6d6dedbef81e9162b8a6028696391a5f4d40d52e8bde21fc8f4df1396b58d6c9d125cf676a93029994d13255f14b6f7ef90fd6aab2e8d0e8297cb53d7faad0e361be240b127d5d275fb84759ab13a7ad8be346518eb425d471b2600b78fbe5218878aa6997cdee9baa4eb483c7d979162ab1418ba5d4de7c2609837607bfd9e24ba0aedecd13d0253aa10c91fa13cce0ea826bd9c4964e416f9d0ce064e8abe60dfdee2845d2c393196cc17f7f5cafcd2fe059b217ff9b97ee17b779401e701c971a99a378635cb6fa1389d6aa5ae5027d924743a3a4c68919efb780e4bae0b725df4e1b1d4f9a5c3efee2beecb428d4ea0b1232e073350c30d86ca6197b5d079bf1c9d0fcb1e705d2b54951027000245ba068b7c6d9af593e8ef64834d47489a673df93960b90c54ba259150e989c941fef9de78403bd7e8e6961811c5e824f43cf71e6a48ecb0c65f14d168fcab6eca03d7ce316f8b3a40c0cf4a5baab0ca4d339aef0b5d027c75daa258941cd6f6ad7260c1bc5c1ffc463b0be9a40ac7f96f90d269b60c8c583e624e0c11aa951a4542df0684fa5c699a5416067d5e2e26d9e28b90bc50b6f9ad2365f31cab40ec0e58d824e047914b97cab112ac35b49ec606d981c0c3083e013be7fdcaa80a2686bda1c58386aee9507801aec128641ac6c2fb6346aeef8ac2e86e122621b7e95131dbb576d6975ff0c12bd7990c3c94a19eb85efe8b682bb526e5ab6645767b9fc86cfe92101773fa7348076ec58c1991cb182a949b52178a353299114d4c20e389d4dee383d6750cad56fe52591635a8dc94af1208782bda71108f03d9a14a41310c4dae567c7dcb22f1f42c6475319cea9701834164fbe9418a9eb575b516e5c64b3ec3952fa51ba06685f0d79378e8e5e8c0b61c662f0dd48b1a9ad44ca7f94bca32ab8affc2d7f1f48301a491d0d61fb47a59e14cb84688f5d6b6a68052d4850d1490da9a0e764565c4c57f06ca7e23341dddf122499ac666eb2c9fb4cc9190ef9c7cfd595f49a12b383706b7b1424d77102738eaf01ed34326776776f3d69ca39b73ee4706e7bef37ab288554bb51e9050fd7d86540db0b550f463a17485483d5932a3962ba3be881298d314d25ff8716e670d2938f6cdb250fc4a05ee338c0977900498d1fe2b194b1e47b6b674ec87f43ca2d4dc70103395ed85b20574c5fe4c62c4fe092262cb3b06ec0fa3fb7eede7f0c9e7461835c73160998b03c3249eb465667b1363875db308e837ec4843a20773df183663ca92b1af0dbf790cf3d3ba94c95668fe939eaf2cba82006755730e94e86f3ef600bba835371552ec4258cd64920bc19e6618bbdfde8c600bfb842c054040fc9792403147d48ada0fad576b0535312225418dcb0c82334a3f14dcfbbc9fde1200e3ab2d7f3e3a993182af99213c0e00b4e4dd3581bdaced70e7116a7916e62bcf0a78668112d43d23291aa30b3acb4bab4d4bda8d2824192bffc4f7eaa5b8aa056f178b6ddeaedb7e38af6197ec370691a6e6819e6b4080aa8f51e412d504656ee70b782995848b1e7e5df415e86a646ce2c86fc126a21fc4b00d3f4927700c53615b79a72da6124854014aa16f6f8e05e316003bf4542bda9a03705c456d22c668f9d5f8cda0231785bac0986001de9d41aeb2b8b21f4996483d7bf61dac2618a42c329fd514eec5c80de4604269cd1f1f74cffba98acd54dbbacf938dd42c9564b145c5dcf21f8aaed19d238f2ee3519489898ad2bb00f235bfb6b34ed913871fc1ee5af2a832b01ad5be44ada3b1d53df21ea0145611688e1ecfc4579f5cd951a04aa8a5a1865b93fddff38aa6bd6f67b43680efa558192feb644672003e95ff12e9d7616108f4bebdccd422e0a46d4275ffbff3a7bba3b9ca3cf10a4202f71e0a24fb98874ea983b7e98de2dc70d3802fe2f9ac074335b1c002f429ed56645d532d8436cd9d068100d536416fd2b48796dd5bfea7048362d70ad1217f17090d388bcad7f7758079e1d0ec27442731e9ca09c5a9033860039617da07628933dd0dd5c8c98956ff072840ff2128749d747c70db6ece43f1a54d239eebac6b380b71437307bb78741da5f310bb10431164010b0729b55c1686427dfd6ce56e5a24c38d4c64f81f3b2ef7dda5a0e524e6302f2577af7bdc9f898ba5930528bb3380b8b57e60ab77ac5e6df651a89a7ce535fc5f615aa057624745d1be6611c591fa3c4ab2f6c235904063f7df82c374fede0ab2cfb983f4a63455889234e41716baebd9fa6d797ee58fa56bdb5b02e50594e1cf0c43744a26e0ccd230545d79656e6ee161f4a27b3acc65e472f89281f4c12bfe8f3c412fd5abc2c6593b6b8ac71c17dbaf42e639dd4b869792418fded79484e56b758531293cab094cf0895c922f57780ac7a27c7e92d6a8c1b859833ab9753b745bfb17c3e84430db225ad04abb9fd5fe5ab337773c3226c2934809fef9b2d9a6e981042508330551f0e7a248e1e546c42d79449ed43fbef745aae18f3d9745cb1d95669c521c1e1375a161209918ea32cb8cabee764637e7071f3b0d0fffab98672ea5bc3ff0e2418db5a76bb7aa28bc5095c487d12c42be09c7ec7c8030b54826af316d3782353d709c62b16d65e65af2d1f17a2655e46674a0bf82f38f2f53bfb8add3b43bd66041a346c9cb65e8d73d53d077c0fee758215942aea0af363b33f562b0614a186afa1cc5479fb797bff0957b49d1b5ca904307568d147e598869d72d9e9516cbebf153b427511c0b10c9792c62be54c51af4bf6a6fd90403aedbb67669e5f47ee010c2369d716774be289391ea80e07d756ba2669a6825ab425430cb9ca3ac1921997db50c424d7a6b9b829dbb3a4a13de16227ad16d62f820bcedd88aba5368bf9fc4f6206f186572898c0fe88509d87ec32f18108490f7404d856448393ae8440668b090146419e3b93008568800432213455cad46c504d51906674c602f1ef66d5a4caf76ec1ca319a80eddc66f438cc7aee775120210515b19107a01777e10cf23a7915bf2ec11f9e3d3defa70b77291670c5cb99d46bd5d89ba4a7019297cecb1014e78882ce25822dad5fa6b9671431bbf83539e7bf1537ce0b152a3e618c0b1285ce2955531e28c508b561b2e11757ad4c71e86e4f56b2f24d65acc5acacc3601f3d69d5622867eeb72d39c6b9860df450096f5fab66693662ca3e6e36d9e0ce8c486856243a9249c155dc6be52f09415d848af3444603e3e3e94e39b188641df7f548265c9f2b0741f275eb2210cbfa22d522b9cf1bd89424a644b97d1471a175cc7dc1a26a0f180dbf97316b8344a48d2063bafda91af0826a37b8e97c64317fefe2ad1c8bf7e80b78981ac14589c11daba097540122105e6e9a99554343f50ca6b9e6ab4a3ad3f005b5ec04c421e84e69feff6003c1e8492024595e31483ae9117cdaafc8b7db08d732618594c92ddcd2a0c84104291dc5e997ed9b4a149d99522ab2245bf225d848d790824e4630899e3e1dfe6f12e4afec92a1952fcc0d3a5ac8b02ef1c98b4735e4e478d34e0837779dbc3c32c7806e3922561605117e632eee86e250f64033a51b27d2e6fb36f9bea0dfa9931a0f76e4c98f142bedd160653a9b1072b258dcd9d5f86cf1c76f14afd79eef7e17709cbf259f94b7fd0cbd136d0ed5c5482fedbfecd845c0dc52b2fa674d51f26826b538ea62dfa20b4d8a41bd26c0b056b34eb1753281910cdc1c149c14da6cfa5d062fde59dde7f29c1a6a72ff8670e4ff6a7260f836ed9527fb64e8b0e925b0c83269fe58b07b5950bdf8cd209f5939713c5e24ef439b2020131c1fa10af61c4afcc81d49909d0a37441b9861bcf4babf7f490bf3c397298c4a475d1614be8a3897595f83cf1b96d56390dfda29304b1eef5acdcad0a15ab4a13c61ac03a9e08ca433aaf9329710c683a7faf2a613fa721c7ca98552a28b357277c30843222db2d54e033fc99a94c6c59111fdf18f54c287cf4259a00ced3653bf01a9f1941abed36a6bcb6f806662e0c82b94ccd760835ae922a81d0b01d7ae7987233e61320228d5393431362d430c8860c020bf2a43444fc05ec36b02d428a02669370ec6bb036dcfecbd3bba4acbb7d65e59a4fbd5580964e60e74476f6662cc58c5dfe8aabaa001e6ea5eee885c69523eba01118381dc608f4c2671e36f1abfcccea32fe08755bf203b6408fa4d982f729d571984902adae18fa71a15b363792a9e013b06a30def5db262d0ec542d933a02c6ed1d9f09d5240f7fbc23d4bcc1f4745f6ad256d37665a57888e9746d81d39edbf4cbecd2a5f4c219657b85885ee35b806685fb0e50e544ad151952ce1d5eb0fcaa05e1dffbb1bb82e407bd99cb5cb4b793f39ff10aa5f1c9e5c158606ec3eec64d60e4a7bcd228a8a2fe5807d68a4952cb29906c0fd627df3019a234f82ce9974c95cfcacbe6b9d6de25b5b1d425b985027967128fc1395e009acb2becb9f339a96345749ad459ff4a8fa749aa47b33ab7aa1b6a79e6d9cb73e46675235eb0a8b1b82ca8c5ec91b694f09c826243310558e062554423cb1d837bb4c06779fa47d7c88e1a5e71feb2c707dee677a5e07baca4001ed4ee9e2c165be2824291dd3f397edb022b03c5b49246a22eb669e3525c92a6faffd400dd53b66973343aed34c5b99480ee0980a8f611b5f5389869ec6b0f7020cc3f73bfed687c06ab5f23c3757c730309240d7840bbc20c4d09b9993a0706890b76d543d37e1c4741f44751ca3549de3f1d721c0a196424d1d2c62edec2172c155d522995c75776424d3ba9b4310ffc50a51863f5895829ec2909a0997d91d18cf8044b0722fa6487a27ab6cc0eb88b35102338c65a62427cc3cb212c045d2c659cfcb111becf2b71b9a2a6e93714b15132e7261dd821966e8dfcc09d86a65218801844f374afea830dc4107d38effe63ab01cc1d6505c8771fa0387a2726fe96094c24d048638e2ba9def73f70e0f0fea802cb733151c652e8c3f512cd5ec8d7c369c092075fbaae060f2ba8a1f0b7f1c6f505d908e5a302592446cb26737b57e038242b8daf06d6feeb2c9a4031654e7d9a8b07fcb529fd3c77bcea6c4fa97027fc292d32b5b834606412e1ab5a4cd25ab3af24db414cc35b6aaf4e2800dc1c3c655b0bbdc2a1501070f96a7839e5ca3653b4596d8210f725fc3f24fbf8e506953d9c2077dfdab76046dda37945acafa2326e00524321283b7d8de962c6babb6a4826ea24b8f6abbe18cf8cfc322f75f08b11eb612bdbbd6dbaad2314e3523ce196a4c7b7ed01a290526ca828b3886b36e316478aec8199cdd4c40dccd17e14c5b8a3743166a41bebf0099f2d38aa1817dfc0c54b04164992416718eed4563357bdea26e952ceacf2a4ce6cebccc3c188873e0b4628e90d2474632753bbe7373db04a528f06f04240f362cb9ca48e67a236309f82602cc62765aaba724d07f542fa0f42c537e8a772203e400f92f27f36f8cba341dfdb613d9bd81857f8fe530fac2c593d92b5138d92c36570d25f70b19dc4c1ea3f2cb60bd9d2cea7a80a3d2e624ef3c1aa8ac466a7ab494b123e4dc026cb1b4528df1593f58971b3f9f6f1b31083eb8b6c40365957e0b3c89b8efd120c6fd16e93915f989368492a44b759a47847e4190409e62b82ece30d1aa63f8a553a70829c7c60a3d627e7154a390b83b1ebe01156b00ba2b1153b924bc9fbde0e01c35b09fac0ab9fbf4e86c5a0cd7fe094a15da00d28532ed2eba4243893aaa7708d6e70519d25bcb2985bf2596086c4cdd020bf330f45bc5251b20723e71a1ff9ea6ba65b0548023690f7f3553bd483a338f45902d4a53dd319234012016748fb642eaf36265ba94010b3d544ebf355322a32836c4e7ffb140faf971018bda3e5352012db80b80fa10a8d287a4c6772f6dc258d933e8404d22387ad40d8a92ba731812f4d7c9f0cc7f02a70b496ef969a56f843312d0d57f71a2f36753ab37dee4059404eb8755e3831a6c3900bce4b25a6cc86a722c574fbf118ab60f5d93cd8dccb884cb06e5501eb332a69b5d90ca50cb328a4d3cd0a62fbf943a8ac87cedaa1b062dee70dc185f58e41e6f6930f77528485f715f5dcb2bac5d49f4d06e1501aedf675066a688af26c84448c114d1e8120ea68584d728067ec03ad23c75bd6caa3abe9c54d92c53924aaed4e2ed70b414e9b5c57f1ae35fb099856e24e7a9414c1d4c26f4b486d238c6304510ee3c4dd18bbbb8ba195dc9b63d0f357a33dc87373822fec9443a814606f44fa13324dce0e099921077b83edc9f19849dd0917e943dc721ae520bf2a1b15d29b8f12775ebc14b5be224c65f369e3d305f03fff87fb5e91b45ecbaea7571905ad14407d079898e7883b3e334880ab16a5bbed13d38e271357f03184d31fd55f66e6e1f1a9d49ce029841ba7672e103de0b0a48c3b71a8d626c578da391c429db8766bd825f3b8ff98c76cee1a76105e2ff7685f4705499108d920dfe2389c2c65222f4ad435c78fa86ad94bc84e8db3ab29823469574c9b596e2e070b258640b33d402da3213cf53c7550243e3f5faca65791ccb4f456ad51adc0e1589df67d0ab448d486155b8b26be4dcbc2bddaf70383a6338fd234a532516647f6b6967a51d3b7f65fcc60af45f2d46028cded491058ead42e78f898a70468e9112d7085fb21792fc74ebaa7afe80267b33fb1e62fd1561b94ab2c94148f94e2a898d31c37ad5fdabbd3754dfba6e48db7979d808acdfa2b85ad4e4637d1bbbfb5add0f67aa31f709da8856ae5ec34235b5f9a170558b9ea06b9ab63b0014a800aa41c716a851bc9e4460348db50bd4c18293719c2f60a2442fb5eea3d33efee7b1134f3328161e67ca307316d44160e8e1257a4499f57d0e098429a13048a105d7d34bde433e8610ad4aaa237bff7271914e526b96564e7a3c210c88192a59f3bcdbf558a7a8e6a732472aaf6020d30821cd3a04a5f49ff7ed41549faf9ac8ce82a32650e1cab5a4bea50f749d51855f76d7a2ba7ecfa0026ef50d9002c1f455fb814ba024122311757feb22ab7c2723a1cd5efe2a55848b347f7b62aac34ff7369b0cb479714e97fc943a136b20fc1149e900e56a9e667b1ea9d2691ae9ec72a20e722d5a4c87ca9d51526d1a37b4dc0638abd12d1f58cb6e02d096514d8f4de73c8b989052e3eec5f7a7fc72a11cf6ac2cf20022b862b312fe4e4dce760ea7d75ec8f01e595966154033f30783402e9eeccee22712a78a8646ad493777177692910aa01e5f402b47d76c27f43b4824b03beb9996c39dec280b3e0ec0ab390c7e4cc00df6314984cec4b76750627afe99eeb998d02dafd64b9505dd39d889d2f0217095963e5f7e38aac3ac3f5531e285808609db23be1d1ff8d4a5999666b984b6bd0a865ef8e195343c8dc6a2fc3b34385ee72f83ec049991f6999fdcb8e1efebe92a71f2f9c788c6bc6b2ddd84658b1ca4a87c3fec78396311eb498d46d3a459ccc9dc5b8362597f9d67abc3ba900afd8bda4bd20d55d22d371f87bd32898b58eccb42dbc524c8294f00fbacc62fffa1e6e7c6b6707427f2121f9437811e72a7ac0da7563d81b0275429e4e15e5d80b67392bb1cf4a75ba0e4ff27c7eaf72681f41c5b94076ae263c0fa311547a1610fd4240ed106c5c5529ba611dc1155a4541562e4c4fff585ccfa3a425516ff917cab5ebd4d5b219795887362628789e9e996de906eeba05ed747c4a7c532b092be5e7c14750f6ef6dac5983ffab22709d942ecf807869653657e89a98eb298e2e24d3ae263fe4f25ac168a715d476c85d532eba1a43448019ab43754a5c0f72c620dc0856dd7bfdfea72ac7fa7d2ce9705c4ff0c6e91106f47dde089cd6796a8c6c5e585cea5d0744a53c28efa2b678e98817411e583191d64ad5c3896a9881cd6e642b104ceaba79a47ffada4851caa7abdfd8803597a4b4c8f38e278d6affd8934ef17c495cfd3382cd36504f10f3eed146539caea34aca98987dd6f6a2ab44f20346477238e09335fe9ecac88f385625b2573710a88a48fa5da761d39a340974ba8bbfb6f1d5acdab9d8b2c7ceb86cd60ca7da608ea7e79c1659346cf59375847d48504b920364c08bf17d465c7eebc57aeefaa0f3312880108b954892aa76b5b70886e1ead98751950a4af8d5446481c7141c3351cedc596a3b132d471244df56c2a3c28a7a3e7d65762cb431a8e4c093401ad9f50f8366e6b24e9d0e6adaf1ccd219adb4e628eef8d033872c41ddb2a5436b91a8112df55813b5ad6bf96fe9a3b5b1860ee2e41f35873fc8141da0a6753120d91ebf1c4fc8b3b58d4bdbbf12449b1c48331d6e36ec303cdaeb58303eba7e478a2249bd6cf81c5e11018463ab8f5a4fca2813ce0eabef7d9dfb310060fc7b0267611463c81ec58753450ab7e7f58c7b3c7c286befcd33fc317c55c4401c1a1dc3617ffb7cd049998449927387e70d519b7d07ac617f193409e6a965ff20953978269c3e73dfeac852d3dd7a09a058d6a79fda1133992caa3c71ab2a85f857a05308b027b017d085d73fa9971e87e527e23299766a1079164e70d1ed7750ef7e25a976e69aee6e35e1e46802b958157043aab9f5b8132a250fa918cdbc69a8e1b191c06c2c433c10342e6f6e7422635058914c099ed0a435a8611e141b46053886315b8908a4ab6a0823aa1dae7329656270d54b9c9636205297171cf4e63c4db4e810078d93d765f78f224562a163a5d5770393bb54b666737a0a13fcd5e8024cf8e25973f36925e92823d81b4d6260365454dc01dab3a02b4190448549996fd8ce52a0cdac9ba702bc485d4a62d48a26650fc11c0eeb60232787508ecae3395529c41e86c024c40cd153474d8698f035e8fd450e41bfa57fedf841bcdf891e077c1c5893d7c5c8dcf0ae417f8d141f101a94ca97a859fca42e92f9db94cf11b70204cdefe9ca4e51934a1225d0820b59ab2209c7f1dab9df65e1bc80a3e9a862ec63f73cd38bc4b7794eec4c67691bdf18d1cf601da22bf100ea9883f7c079be1b45647b2685cabbc5f5ac0f43fc96ebbad1e3ce6c7ffe25e72387d0ec9f3efc81de04e8c6c1b3a900aa7aa9703394def15d532d649064b40ddd3fc1d71287bd5985667356034f8a39576b3492e9d6c4e1f685e159b40085473acf9bd1c9108d8b4471a62ef613d67fcf44b73f22ef17a03c9d10c310449479f710f7ffc66784d065beeea0977b451c98422f629da448a54bdc442b1e19a55e8bac544f6122b1b7d185ac3bd4340f93c3063dd337940b530c39c443d17f15f1bb7052402ea380961ee19a83271eb9c53341996a55ef77ba58a696e3cfd7c37b1b992047985be1a7bd26b053571d0dc84b1265a97d03614c2d45c0df3b61d09c790336d24226ba600c821d29f8d694bcdde887fe9f0c0fae0ee60ccbe55a520eba4ecfc7c9b734612dc9ca777571e63ea32b1738677fab634dd3f0e07d625b045142142d3e204ff5f937883c0fc6c9855a971421e7bdc38bca00cc9ad32f6a556ab243612d3964e30574bde4ed1abf7352fa1dd7ac0bdf387bcec1782ed6d1012886e81fd3e919a53c785cf0c28aae1248766ae9653ac43632c4f6d3123c240c6014ef90111248952452c5a8f19c98e1a97e9d856d7470df70046359900e01b3ac906fe305277d802781a7a02e5782bfea2fd290cbda2d367110ba39c1e3260a1b41d88126b921e1c34f8578a5715303d80d227de9aedf5337b602165972dc9676e40b9b118f8e797606271d736e42b518f74ae72a3333a847a79299b4de1db49f426260bdd5454fdf18b56daef690264e7e675b856fdade54fef5aac36c52657927c1afd0868c13b7ec29be409913cff2b9f357c7857b83321b3380396de09abe5517926ab23b40c68f8c971e6c357ac81e6694b5d23d2674711acc817b1dc6a1e9cab51bedb61eddd5b0d6502fc766505315e2993bf6cb0136f8fdeb9b9cb3ba5bae4d1a95275c1a78b159ee15bf47fc7ca1af3be779ef0c7a3f45e8b66b7c0f03cc8870272ddacef8efc3e9e1867e2ad2958a3d48800a8352a4a3de143f93254389db5330346705d7566c2a24e2a5c4eb5cc432d3e55e8aac37fe77903cf17a13e9e5da6e52febfb491528370980624db7427366cc841aba23a6680aaa39ee760f9c857541e6a6bcbf2a66e8197078b70361f465038bf9a1e44be41a48facc4c62972d2a2303dcf07f82b7ee979a31e292ad84009b529ff0512f13c9cf14ba87f5da317d0e3b468e9ab258fcc87c87c6cf0aaf7db05345edd6309e451704e85a52a2942736e69d0ff9a4ab7b35450ea9162286711d4906a5ce3ea7d3f79c95c93d772d10a39aaca284d118f31857213d9dfce4e0f2d80830c0816fa8c6850bb1f0a2a117879185361d7ca996ec4f94e21bfcf117e396de524f3e3778540bc06673decfc447b8536574bf8166febc99b876ffe55e6777e8ed486cebbcd594a307ba3d5da6e666dcb1ff95880614675aa92bc3f1dd7630ae7b84c07abdd42254b9f6961246f2f284b12e0e32265603d0df6d9b99184d8acd3b064a4bd22eb031e244d269308d4241b05d49a5ddd2d3ebad6701dc8eef502cf633d9892cf84e6c1bc2a53ef2121e8f791bf2fe36d631b5f3064c5ff47861c969c505b5d2041cc68d922bf12cfc6387d124b2ef3b22511481e07f601765930beb55e8781aa71cddc70856729453aa7350719d9cacc1e23f87b64c70b0ef52b421faf36b393f2a57889e42f59fbb16ec710fee23d770b5645160fd5194ce609b91291de4eeb49588ac272219fc701f29a2c3fc50dcdc0d2d01954a910b963313b61dc88260c7c598ab3bc79bddd57ca1d42cbf8f1f0d4b8186729ffbbeaa668550fc36e510fb3c5970804272f57c7622f51e63303ac3bf5b0ae45cb28b7c985889c39ccbe15b30c3909d093093aaeba34cd089bf87d16e07257cf21444863ec1d131a5e8a5724d02959e748919cc18bb8311d5c7452f390883f7b693d2a0b54519a6ca41f9f35443a85ca48e8481cb350851bea417ba42be4b3bffc76a7e71f1fbe9c9a8319f61a7abecbbf218c377c0ec1c5512ec379ab333cfef78a0f88bfa516e5b0dc37b2b9387107cd09c0a68454762f69d4601a500a0fbf1a5746c22efc2bda7fe595cc53263fb759eb0adf651ce221836c34c8e018a9d5cf7f11f0b49adbd2f8b844d6bc889a8a12d52f96543da3ac3d20f4f17509e76999212923d584a50626b54f4d50d0a389db3648d29371df62dc49ff938c4ad51d8e49805f266555bcf22bb261dc8a8efc0ca6f6d29aca55e110d92eaaae583d4cd784529f7998fbdff084dfc260eb1af5e1ed3a43993971a923b803bacb3cf3a493175152e8ea3af1e1862a467bd1d29add3a47f6911d651e4a526da163b8da718ff5ab6f95d7468cbd7d07b0323a75cdcbf7cd1170d185ab74e47fe508ffaa30fd847e38fa2b42bcb83cf67516db1b773c6c3d5a5cb22f425cb57d62734d1534e816c2fef0a7d30821beae76e216c251e9e55fc1db5096cd28dde7943de9858bae95b7e7032f2076cbcc2b7d934219ed0d3b29cd049ee94ec5ece7ea9f0c6fa2faf6615cfac2caa63424c72817baa90807bae132b06b21567393c8ab71827e00103f0b9cb2a6aa8e50f5260a301d36d6e2e29fe51d46f50b1a7fd7e89a790b98fe62bdae71b24981e1285ae27a8e2e4eeba9e629f477db6378aef7d68492553bf89a955b4ae84f96927035e374aafd9c7f49bc05de73089991669eab370d7a69bfa6f322134b78e67959ee7a2600efae6f37bddbe6c6aa49a068bcdcb92847dad27b4cff7b37bfaad5b7e441124e19eae304059ffe9fbe1fef5b0f153566c05ba49cbc75a057ef7f5f336a06ba58a4cce365cf207eac2ecae5abb2d9077bf252737abecc3cf30b9cbb68d66a69624eddf58e9c8d8e20f40cffc0905bbcfafb57c09571e635f3452e6a459dfa0d548658a9fb0b1837d10478c8b17c1300b42e8eb462eedfbdf85c5b7291c59a05e8bae729ca8fb7e9c32a00d8bf943f6412413f660c9807fc931294e5788ba2f184f2bf69e67703a868be8f0b7029284768f88634a6a185a37d1b4ae0d7b858837b2e23b07d9fd045d73849e5a8cfb279940ac515ca97131e703455ff844d211b281761c751ffbeb44059b32d6a8a8da2062e0a493db7cb050e3443d7f76e37ab19ddc5996828ae143c40e753f64a433b381424363dbd9ce965f84d001c686de80a04dd270d4d3e2c3a9ce3a5fd5e8c50e04280a3d3512f90759f2c4afe03dbbeb8cf183391ce2edae7bc81b62699ef006874cb0c95b8ba5ce0c5361c4e8ef358f106aff304c30acf17015144895b812b4a61b9ac841d8f4402f6484b275e18350278471fbd47981fca3a0be0e5740ec259867f4e88c716379f4fcc43dcd432904918a0e2a4e2615ec7cfc2584c202722413c8a843bc3625ed9fe76da0159d85ce5ba462c23d390f163e7b08c4c1f160e8b4989cad558d913696b06817912b730edef40ae3a1d727783ddfb5fbd0a8271d6d624253957b6209a3e2101afc2d2df082304be41b2141a6e5c38eb13df0874cf402c9cf57f6735dfcf0422e86efd775fc578d64f78bce8a0b1f367a0c7cb009935f30c13a7713b029f6ec3748334b3205c5d2ceca3abd81f032003cc90b6fb23cc284dd690d1be1c2bd3602b60891d3a52982858e275eb6a1ae5280145c34c207c556acd3eb36d771f10e13b1f3a1101c047328e40d4cf45bf7970f14d91c61811d24a852257d9bba4821db57af1b326100fe262b492fbd7f697fd86cf44b5a59c3e86d2c22608bffbd534846b9bedd97553d7a047e834249650679a7d018e9efa60eef00637439841e761b481cab5fc88fdf3c8d1d61e22005790c9b1b52da8160366b372087f3f7cb1eccc303a85a8879a10fd6cce12319c9f64b95a3367d885268d647a2ab5f43166b2d5f94516b919a55c6a03516207dec1c0e73ef454c3a52487552109cf635c1028883040af0969352b04f142c5ce8a2ac5a37531dd7b6a3557533c0ee7a25fb25eea77de284898a0e5b57066c1edcaa2292cefe1bf43960d7723c27f56b3d5054d037cf14508571a36ae42ba5f9eeda34bf5915907869bacc66ad83d2fda0ed5ca9e3b073ae8ec047d4add458669015850c248cac2f8b39f2da267264e7bef215c6ff4651b36cddef2f57453e5ab6de7ba7a7999fdc66fba3c60cf8c070dc2e0bd28c9f4cbfa049f4af736f80bfbc80d585831d544f961684a35b14a41dd40111c4274d356e9f2fffbb4eb77b0edd58a4490a34f5a6b834ae596f349ba131263b7e7318a4646c936475864fe6a14b0fcad82eabf7a355ef04ab0718a8a3cffa114c551f44a6a71b864420036885b89c998b7f47308426700b800176268b6b9cee4af3be48c003e6126cf4cab9ff061606686a373a21a7a4a61ffd7df5eb769063ff6bcc3682c5ec432757df673f9aff6c1a5e8f675790f8a6b8751d7c79f8db32b302c1d3a9b5108e24ff30c1f2e68b4801ad433b141a46e9c827c538600278e65a51f8ebeb8194c77fc99ab4c91a6fdf75c292554196b8eb006e652c7c97018db8ce3f7a21a73296bd269e6fc1c42d3d02bfb145a5e4202d6056f40562bddcab9e81e69add85439c933ccb2dee1b333181b2e174802c8cda0ce8bd936e20a418794fae6ed58c0e9b5ea91e61cedc091665bd7038d7af7cc9175e6457fd626c351aa03a5d76b86e8f090624dd7a6575c3f17994423f9d70677e3a84d2965ee6d4f70614d7c8998b741a9e9a81362a1b3f7746013f35ea2919966e3030799dfb7e263e63ed9a9a936a3775c17ddc139a2aa369d78777b53587088739a8ee9bcfe03f561541468090308e6d21db9bde1d40095d34a9e0a1513a7fabdade1309fa77f80d4f51bf8f92cd49cf74e48b80d0413fc9fe861e91c431838091e61bffe94a9a8f9b6448660dc7c3fb8ab8c6a9467c4b580fc6c588b702945a125368261312a9c40e781066b77dfd95afb2278b4a737a0ddec847b48045366688b9424a694390a111165ab4b28f2da525cffdd81f0e3624e10a52ba2f3891fffaa0ba1c650ffe4509794a404126470d811a81ddaf0464d5a8cf31b7238e75ddfa9999f975136353ac68eeb39d1a4f66a71170590e6ba91aba97ac7d039428c85fa425d6d707acf1411618a144f08549f74ac6938fdabc25e7b7a44edd8b3213fe6dfc62046da4aea5f4b85d48c09c01a994ddc9eb0c5a190416868476134b991eb66f16b224bc770cb2df36f42a33b413d36e3f02965f9a2c3bbfbca15be770786376e7b35e7c5a1c390ca07f98f358b981fa18a0a0bb6802d3a67c4d2545252e71ebfa6df775982ae70f9eb737ced39f1921263c16d261f5cb1b84dbf1a3a578fd9460cdc6122265527d34a19480ec6851cd28b0740a5535a9b45d15fe0f9fe60cfff4e8bc840a14ad0388df257375ef8c0729eeef028cd6aa863ea0cce6951d4a6adbd0052ea14349f4726ba763d366319da7e48191ae3faf38a03351e4a5af31c70e3e4f69cf995d783853ef70a9570ec0c7fa1893ddc28104bc29b905e66d618434d4a4c80e5e1503a771751e3f84836e63c020f7d264cd62cb39acac61b53609c3a399e2ed4436cbb5b83f185dcccea986e5371f030bb0e3a25316026166aa81c8a8a3154b2591c52552f1c30da447a2f8377058202dcd2dabc90976bc9b3a0fd1d782c2d9b3fcd68ee62dd5bcd2813c4d80025337a5dde84223aabeb91a12a52fe38fe7f2e5d689ae07233260783eb1720f652d20789dbdb794dba5c941da246396a4de7cf19fdf481ef78ff59be601f0a220b7e5991b25dcacf8edb5a637105fb139c8d7d04d9e88fe3559cf133aa38725b8a4cb00a491652676ca731513d7e03bca1fa57b648a25f1f7ec079b7a1aeec7598e1c0cd228930df20e2aaf0fb97c8cb8e4567d119d3ac25fee1c0e031575eb1e1e6cbdf7a6dafc444055ab1646ed0e0c63774b222b99e08096a0d6a09689dcf8b80271f0082babf29a6260a9ab5021edec8e6a3c7f915e0b742437e420443def7aa3f9aedbb3089fd0473200c31d7ca20e403d3bdcd40b6e73dd772610cd582a1d07d07500f8c043a1098fb3a120d93ddf836c3775a5997b9842bdfdc78615dc83d7bbe97ec7c1c3d4ec504158ab297b755facbc9ef00caaf5c6a4ac45e9dba22cc5b73350a107e123276b84d96601fed3f2e1af18ffa29517dc9cd046d273428627889fd18ddf6a8ac8901509d53bcb3026c62570a0370505ee1d6baeb689955c4b39bbff2fe875e5b9d3eef2a5f61b570ef043bf8d7b7d8090b37364cf01f7b5fcefb538998eff4fee8699e97fd0c91a62c4960b64e12454eb31fc19b3978baaff0c43bba5132c12c27a8817a3e2ac0bb37a74dbaf602504d61538ebcb03aeb277acc64760bf3e0ca2df55da1bcbd00187953c3cd968a90b74beddfe008f90be48bf959091b68f2ce78c0427705411b23fc2e764957cee78869647b67b61da29c33403df1c075730af2246ad2bbf059c962b84dcaaf2de43237578b2efb92b1f66cd6c29e5f5adc2304a87bc416bd71c53350541d444b768f9ebb50ffe3255001f0fc4fa804731710025f253bc005adf1aba619ef6168a5722b185d5075211abb9b09ed00db760dee50167d39777151d14bf12ae9826ddae793eaf601c8aac2f1603dd3b62fdb91ac326063c999e668d7171c98a91705a6fbd617041517afb93d322a823b06ea31a0d6129b0ff9d060305d6dffdd764d02efc129a666ecaa0f109c4a30209c4bbf2cc2156e984c9663ac4bbd655a4a9678e735cdd555c9b73e34480e7ff2878c5f0c29e6d2524ebdc6b67fbd291c3f8509500460649f3dce066879ef2c2884902790fb1309d3e3ecb6dd42179983bd11dc7c6180f27edf97a1563c385127d43166cedb710db3eb326355d00ac08aee1ae4b2b399f357695a41b25ee6dbca79d973e294a25eb06f5159c44f129e2a4068d1dc1eb8f1512dda907a11b911c85a54800f65d91e5dedb9cf1fe7aa027e3fef4c6de92c73e56f96e368acfb62fb156609c72dcf3fc882f9fb889b15b57840114d3709482805b02614c494e95cbc5e382c61857a1726ffa7a88cd135fb8e7ef8e8f24169aba8a356c0a1cb0bf90b26f0d6ea59bf882f653d7630503054c2e9785b21c83f9c93a33dc13c1cb3e7f3d8fd5f40e0e92af02cc4dc37bd1d49bb87dba6d410523b4031974279d9275920fcf8dd50b72e781161bd8a6f5a5b70b096d94c671a0bad05b3ece99921cc250884eaf550e685e12a6e00f59c8a8259c492973ed998444f5b9797b6c342a49aa808c54ef3dc1a65ae297db972936f7cb88fe731d572f423599630d979142643e263e5a773d30915fc2ed0d785197c6bf6bb86156607b328a58a4bbdbd8bb7eb4a2cca4b9ce799b20c8532751c2e088f3d0846326a69d42db34360f8e0a3c5ac1cc5dfb5ec065d68f2b4e5755f890491ca7e56b65a9e70817e50683241b2079fa9fe7f537f67e4434bd5dbe9b194d6913613143ec838a1ab8b219511124290a1d927944e270325cf7bbb21c3a01fe787364101d87777bfef36cc977e47f787d0c39e604f840834d9f086609a28b6b49ab83155ef32cb6193a9abddcb06a6993cb40a396c1e085f600347c2b7ea619eee2c5bb3eb816d2822c46b47d59f1b639dea69ad6a6fc19b2d5418eb624d5a92f26e550e71da463a9f0eba29510dec09e59977dbb9522c9eacda7a6ce1f07908bba9999b86087987c2c38f2c45f85a8de97716957581746b992239e0c96f6d275e9d07e36713de9a5a3becb94ec5621360f8d248a310075ff378af138703e50329bade76649dea85a90e5f07729a94cc8e4f48296f0a05c36c82e3500e6f46b9b1db46b420c39de4b7d1fb13e89bbe469876ee4b244f3778eec28e65f3a2c2e7b2b311e6f8d365d8988d5822feff28cab30b95fa085e2410d5eb82f5480793a9e8fa27063706b5f011d5b7339c03975413b49ad48103dcd770ae60d693b954a07fa8b9e0f2b3a223d82087ffe594d6d7829600273de919a96d0f2452c8716b0e2971dc02a61525f8694b8eba3679238b73ba37383d4718993a0646bfa1c85b7e36df79ae1261ff4ca2ce7b777e45a1a3517acff247e2222ba73f65befb42d94faa88a8c145af5154477f14b5a3cad90858143f159c5008cc5ae69a762298adf36ede7314fe0084538acb9229198e301e0ebb5ef62ece69eca57cd1fc0b905a662c98fa62a30bedbd22ff797add0a167e1e953918b132dd4cfcc8bf7b3ce1cf3002f8917dc4552848c9bc21771fdceb0fbd77dd7618123234b6743fd29dbb18c23b4eff50e38e0409f2a2cfe4bbe734ac85d85b5fc05191402986dc2d4a278956e4fadcc1d641158c05428f7128138c785bccc8c06c59ba5b8988c1c3e5fc92bf40a959662879fc2f4b00a462335ce971e7f7b7553261c798912ed9872328842a1394c84a2af5f1da00fd5dfaa87b37964b7ace8bd7e110aa7c7c65fce19a17c8049488e80d95cea228134b5f05d3f17cdbcba1887fb38279bb6864ec4ec191f1d8181784b135b363978b89358ab9bd8bf0848c1bfcc1934e2de2eaf3f5d2dc23d53bb0f415ee675bac37e5d1e48585a105c9478cd94ace5d1059fc3258f7cf8a197c9bd0ec4658f223053c53101240ca478c11bc6dd8b94462c1243807156080b7f827d94ec85674b703f5fcfecc7f90af2f65f9ba70bab70e474b37b2544a425df406dd0775a5d8719e2316963d53f13708b31a67d7a996ec0b1c4e320dfb25938a4d081e1009672e318779468ba2d5d507d924327919f0b7f76bd45a306cd4fbba5b2a0e945eab386caba321d452a62ce40d1398a7ca5e447329e657987178f006617ca5191dee1676d7a3a566f841c8b82cd9e89bf947c3fbee75125093190d512cb70bc167c29f62ce2c4d82c7279b27c011c3a1e5adb5dd8b5cf64a250c590a0f13be4f38ba4c688f6af4496c396c1ce97cd371499471e890f1a421b94d404192af783fcc4b7996a5753725731782f8b9cda9f82fb9a089c4bff3bda28a2baf48fd97443bfe8f95ed711efe9ccc4d2e1b65f5d67bc49503d8fcfeef5df2300b2f2df07382924451c22579bb55fca85f02e8fcdabf2a2ece3f429204423b39372379dc6d48b350b5c16e18ac78cf212b2655bd8795b21b689039e49820f4e6a0299d74ef23968ffce5c98393395d2833c092039a02861040a9253a0611f40ac89a828c9caa407cf9dc57d8b048d5a07341b8f9061fad1d678bcbe4988db97e9dbdb353e7a8ea5655554b9d7b5992d4983a6db77c5ec95a462354d0db9ca680e13ffd6ac07f75f52462151f914331f89b2dad85cd88d44bf800d4c6aea0fa9c48b7fe25b3ea46ecff43c89e285cbad27ad0ae245c46be7d0b9eb188bdabc3b9b501c4fd13998ff2498aa10cdb52f8e9aa2180b52dd722214560934856cdd413a0844682b450c072341c396fdb1e7232c83311f95461b43d907a6cf2052570cdcae75aec4ebc2d21e111223d0fc4d75df4d53d3bc893baa3fb91ee99b8009d76f49cdaa476894237758fd795f987ec95f88ebafc6e509a9c56c704d1e07772191bb0a9ea2974451471ff1131e8fb0880efec56f6bf6dedcabdc784ca30190db8aaccb5d972ee5227958df1586556fe6c9bb7fbfcc2dba5c2b9c78961327635d147f663cd76a5442dc54e0e1d3930f627c8fb36bd813d59c49a62f5c157c5b9250e58aa02851eea9f6a2fe14857750a558260552d504bb9039d777572fa71f52e88a1841ab10a54b7aebe94046a9a2c7621c4df3b6142fa3a1e2cda6332b927a484fb9578186e5e9f47438f4a2a123e3b7b34c88f5c51739649e5b87c5e0fe8ecd68a6278ce0afce79a7b82010fe7f41d71e73d804601364a3dee89b9b919d51e1b8f3fb696fb9787df427d46e75db528a051fddd1e4c314c3da0ca15e03c16be82a0816fc0840189b0ba45523e7fb1ae5a1c98b384689d8775ac7f675f7f1f4a28368032b30795986ed95033607aa72689c44551243416db292007da123b7700dac53ea18973b24c63e9f8e0331450d672b99d1a9bb7116444c01f46040997d6c720d836e0daa109368db89927d2d6280b22684f581cb129268295b281103746348c288f0e904989ff638892ddca22952fde2cc8cee6dcc4b3601f22e7c27f1f78427c324d57dd56437cb31462909da1a0e1485691a47858c36034ae13a2997b7569d8a81a62494bc56203c57a3c9a6bfa3684aea392df1a537ddaed992814dc81719e95e443a21a85d03f633438d152b2df343acd7c2c570f3b2bfdb0a057c86b3d800c827fc1d4d39a4f6b22f89c3774296da68ba5f37542753eccaf92a8d0742951dc2f4cf4a0d19de7456ad4f7cfeb1a0f6fcf9af6dabaf462b4ecced3d195fe1b2e82bae23af088ed48f9dcbe3704ff614adf382373dc8dd9432c39cdbd48f2730e08be81dcce2179494f98da010b7e6164ddd88f7604b1e813505b6803d9611fb22b86801b986ee8d72a5e6d25dadf9f13e4d7c558e045d6c9ec1f7a607414ed6726d08ac780a2dd5bf5cb03c8bbd896fb0d94aae4925eb2f24ca2783b7a061d9bed376b3724ad6393ed08c817aa5dd9ffbee22f3656d0948d312264976dae5c6b2dd5fe93dec513c13680c5371a6f742957e248ecedd5220472c28c930d2f2d863e52d15af9e1570a88b01c9632dcc7f038c4e264d83997f3694751f808788a7a652b5b00361b7588a0855f6fd123434766ef36128b2aed370199f1b98d62a7e8f75e6471e248cd7ad615d1cf5a0e037d894a007dd467211ed07f0564777b676f88de294c659b5b7ec9dc46f68529f518d85d5c9be6b82ecc73137a7c3a9192258d189ff7efb598d202c501c7606b48c899b5c9aba85aadabc1d67c055d998d2321016823e4dd6c2be473bcde5ad5c7f4264ecad21d7252bc5418e74c99d7db7675aa9b5383dddf1082eb6bbe1efbbd05487ef3a61315eef3933d32ddda3360712724cde070e4ed36349abb3f756881d3dfb7fc71e646277abc197662d1d81b24b70663b347c0e06a2c48fb23fb4ed42716a72c09033b386563a08968c5b55dc9a77c7789896ba14266d3023d388b1811b87d21454a90d8d5853183d3ba3d3d3f8af59167d120ea504acb005d73a8169f59c8c6cae07dd77458f9b28a11a6f08d65acd478c814d0eccd98ca43ba251804df69c446611a42977b6ef9c09cf906329317c0930a6e15832957e8e51f34ddb288408d57a55ccd6e9443cc17a81ad57bbc52928e855214afbf1fbe48138fbb25a71df3a1cb2abe803df77e7f7086ba591ecb7f098b0d96178c161a9ac146fa4666731ceb355c7c48baf392f2f02e3545d448c0237c4b552a6e6cf0cfcf28e130ae50e41a9c491bb05d6baba768677bbc68b682e136c6829fc30c93a93276ca96ab5170e3c41d47031a0c1de7fd5dd6da9730e79ecf095dda3ab815e3a7f451948a098bf915ca849de967d2a11ad8ff0376172e67b065364d3bb28f9ce095fd7f31df4c3e499d6129ac17d3e1a243937503878833ebc0280f781c3ac14164b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe950fc8893ce690c41c30bb1a9846adcef56fe53eeb84398327326ce74b71f9069214cebea7c0677ad4c1c530bb2516bab0ca560779be256a7260acf5d576b9b3118d409387e386ddf67b1f02a03542b092edfb32be734144f947a53916972e39d515f7bf0f4839e721dfbf7814e4a990deaf77cbc2517c38d54e651caf8a34dfe0d59daf186fbe30b578aa59f9add67080011d2b490316ec124cdf0f936282d5d0b3ee9c1c79fe5f6cb5d7a3359f607b62472ea5bdc75008d17e4e608e514be761c2" -]; - -pub struct UnstuckSnowbridge; - -impl OnRuntimeUpgrade for UnstuckSnowbridge { - fn on_runtime_upgrade() -> Weight { - if !is_bridge_stuck() { - return RocksDbWeight::get().reads(1); - } - - log::info!(target: LOG_TARGET, "Updating beacon checkpoint to unstuck beacon client"); - - let checkpoint_update = checkpoint_update(); - let sync_committee: SyncCommitteePrepared = (&checkpoint_update.current_sync_committee) - .try_into() - .expect("checked by tests; qed"); - let header_root = checkpoint_update.header.hash_tree_root().expect("checked by tests; qed"); - - CurrentSyncCommittee::::put(sync_committee); - NextSyncCommittee::::kill(); - InitialCheckpointRoot::::put(header_root); - FinalizedBeaconStateBuffer::::insert( - header_root, - snowbridge_beacon_primitives::CompactBeaconState { - slot: checkpoint_update.header.slot, - block_roots_root: checkpoint_update.block_roots_root, - }, - ); - LatestFinalizedBlockRoot::::put(header_root); - LatestExecutionState::::kill(); - - weights::snowbridge_pallet_ethereum_client::WeightInfo::::force_checkpoint() - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - if is_bridge_stuck() { - log::info!(target: LOG_TARGET, "Going to unstuck Snowbridge."); - } else { - log::info!(target: LOG_TARGET, "Snowbridge is not stuck."); - } - Ok(vec![]) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - frame_support::ensure!(!is_bridge_stuck(), "Snowbridge is still stuck."); - Ok(()) - } -} - -fn is_bridge_stuck() -> bool { - LatestFinalizedBlockRoot::::get() == LAST_IMPORTED_BEACON_HEADER.into() -} - -fn checkpoint_update() -> Box { - Box::new(CheckpointUpdate::decode(&mut &NEW_CHECKPOINT[..]).expect("checked by tests; qed")) -} - -#[cfg(test)] -mod tests { - use super::*; - - use snowbridge_beacon_primitives::BlsError; - use sp_core::H256; - - #[test] - fn validate_checkpoint() { - let checkpoint_update = CheckpointUpdate::decode(&mut &NEW_CHECKPOINT[..]).unwrap(); - let sync_committee: Result = - (&checkpoint_update.current_sync_committee).try_into(); - assert!(sync_committee.is_ok()); - - let header_root = checkpoint_update.header.hash_tree_root().unwrap(); - - // Header should match https://beaconscan.com/slot/9094528 - let expected_header_root: H256 = - hex!("84a581291c4a4fe66879c4647a1084ee584ea5c8ac82009aee323a66bf865e82").into(); - assert_eq!(expected_header_root, header_root); - } -} diff --git a/system-parachains/bridge-hub-paseo/src/bridge_to_kusama_config.rs b/system-parachains/bridge-hub-paseo/src/bridge_to_kusama_config.rs deleted file mode 100644 index 68480a4..0000000 --- a/system-parachains/bridge-hub-paseo/src/bridge_to_kusama_config.rs +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Cumulus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Cumulus. If not, see . - -//! Bridge definitions used for bridging with Kusama Bridge Hub. - -use crate::{ - weights, - xcm_config::{UniversalLocation, XcmRouter}, - AccountId, Balance, Balances, BlockNumber, BridgeKusamaMessages, PolkadotXcm, Runtime, - RuntimeEvent, RuntimeOrigin, XcmOverBridgeHubKusama, -}; -use bp_messages::LaneId; -use bp_parachains::SingleParaStoredHeaderDataBuilder; -use bp_runtime::Chain; -use bridge_runtime_common::{ - messages, - messages::{ - source::{FromBridgedChainMessagesDeliveryProof, TargetHeaderChainAdapter}, - target::{FromBridgedChainMessagesProof, SourceHeaderChainAdapter}, - MessageBridge, ThisChainWithMessages, UnderlyingChainProvider, - }, - messages_xcm_extension::{ - SenderAndLane, XcmAsPlainPayload, XcmBlobHauler, XcmBlobHaulerAdapter, - XcmBlobMessageDispatch, XcmVersionOfDestAndRemoteBridge, - }, - refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, - RefundableMessagesLane, RefundableParachain, - }, -}; -use frame_support::{parameter_types, traits::PalletInfoAccess}; -use polkadot_runtime_constants as constants; -use sp_runtime::{traits::ConstU32, RuntimeDebug}; -use xcm::latest::prelude::*; -use xcm_builder::BridgeBlobDispatcher; - -/// Lane identifier, used to connect Polkadot Asset Hub and Kusama Asset Hub. -pub const XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA: LaneId = LaneId([0, 0, 0, 1]); - -// Parameters that may be changed by the governance. -parameter_types! { - /// Reward that is paid (by the Polkadot Asset Hub) to relayers for delivering a single - /// Polkadot -> Kusama bridge message. - /// - /// This payment is tracked by the `pallet_bridge_relayers` pallet at the Polkadot - /// Bridge Hub. - pub storage DeliveryRewardInBalance: Balance = constants::currency::UNITS / 2_000; - - /// Registered relayer stake. - /// - /// Any relayer may reserve this amount on his account and get a priority boost for his - /// message delivery transactions. In exchange, he risks losing his stake if he would - /// submit an invalid transaction. The set of such (registered) relayers is tracked - /// by the `pallet_bridge_relayers` pallet at the Polkadot Bridge Hub. - pub storage RequiredStakeForStakeAndSlash: Balance = 500 * constants::currency::UNITS; -} - -// Parameters, used by both XCM and bridge code. -parameter_types! { - /// Kusama Network identifier. - pub KusamaGlobalConsensusNetwork: NetworkId = NetworkId::Kusama; - /// Kusama Network as `Location`. - pub KusamaGlobalConsensusNetworkLocation: Location = Location { - parents: 2, - interior: [GlobalConsensus(KusamaGlobalConsensusNetwork::get())].into() - }; - /// Interior location (relative to this runtime) of the with-Kusama messages pallet. - pub BridgePolkadotToKusamaMessagesPalletInstance: InteriorLocation = PalletInstance(::index() as u8).into(); - - /// Identifier of the sibling Polkadot Asset Hub parachain. - pub AssetHubPolkadotParaId: cumulus_primitives_core::ParaId = polkadot_runtime_constants::system_parachain::ASSET_HUB_ID.into(); - /// Identifier of the bridged Kusama Asset Hub parachain. - pub AssetHubKusamaParaId: cumulus_primitives_core::ParaId = kusama_runtime_constants::system_parachain::ASSET_HUB_ID.into(); - /// Location of the bridged Kusama Bridge Hub parachain. - pub BridgeHubKusamaLocation: Location = Location { - parents: 2, - interior: [ - GlobalConsensus(KusamaGlobalConsensusNetwork::get()), - Parachain(::PARACHAIN_ID) - ].into() - }; - - /// A route (XCM location and bridge lane) that the Polkadot Asset Hub -> Kusama Asset Hub - /// message is following. - pub FromAssetHubPolkadotToAssetHubKusamaRoute: SenderAndLane = SenderAndLane::new( - ParentThen(Parachain(AssetHubPolkadotParaId::get().into()).into()).into(), - XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA, - ); - - /// Lane identifier, used to connect Polkadot Asset Hub and Kusama Asset Hub. - pub const AssetHubPolkadotToAssetHubKusamaMessagesLane: bp_messages::LaneId - = XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA; - /// All active lanes that the current bridge supports. - pub ActiveOutboundLanesToBridgeHubKusama: &'static [bp_messages::LaneId] - = &[XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA]; - - /// Lanes - pub ActiveLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorLocation))> = sp_std::vec![ - ( - FromAssetHubPolkadotToAssetHubKusamaRoute::get(), - (KusamaGlobalConsensusNetwork::get(), Parachain(AssetHubKusamaParaId::get().into()).into()) - ) - ]; -} - -// Parameters, used by bridge transport code. -parameter_types! { - /// Number of Kusama headers to keep in the runtime storage. - /// - /// Note that we are keeping only required header information, not the whole header itself. Roughly, it - /// is the 2 hours of real time (assuming that every header is submitted). - pub const RelayChainHeadersToKeep: u32 = 1_200; - /// Number of Kusama Bridge Hub headers to keep in the runtime storage. - /// - /// Note that we are keeping only required header information, not the whole header itself. Roughly, it - /// is the 2 hours of real time (assuming that every header is submitted). - pub const ParachainHeadsToKeep: u32 = 600; - /// Maximal size of Kusama Bridge Hub header **part** that we are storing in the runtime storage. - pub const MaxParaHeadDataSize: u32 = bp_kusama::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; - - /// Bridge specific chain (network) identifier of the Kusama Bridge Hub. - pub const BridgeHubKusamaChainId: bp_runtime::ChainId = bp_bridge_hub_kusama::BridgeHubKusama::ID; - /// Name of the `paras` pallet at Kusama that tracks all parachain heads. - pub const ParachainPalletNameAtKusama: &'static str = bp_kusama::PARAS_PALLET_NAME; - - /// Maximal number of entries in the unrewarded relayers vector at the Polkadot Bridge Hub. It matches the - /// maximal number of unrewarded relayers that the single confirmation transaction at Kusama Bridge - /// Hub may process. - pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - /// Maximal number of unconfirmed messages at the Polkadot Bridge Hub. It matches the maximal number of - /// uncinfirmed messages that the single confirmation transaction at Kusama Bridge Hub may process. - pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - - /// Reserve identifier, used by the `pallet_bridge_relayers` to hold funds of registered relayer. - pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; - /// Minimal period of relayer registration. Roughly, it is the 1 hour of real time. - pub const RelayerStakeLease: u32 = 300; - /// Priority boost that the registered relayer receives for every additional message in the message - /// delivery transaction. - /// - /// It is determined semi-automatically - see `FEE_BOOST_PER_MESSAGE` constant to get the - /// meaning of this value - pub PriorityBoostPerMessage: u64 = 1_820_444_444_444; -} - -/// Add GRANDPA bridge pallet to track Kusama relay chain. -pub type BridgeGrandpaKusamaInstance = pallet_bridge_grandpa::Instance1; -impl pallet_bridge_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BridgedChain = bp_kusama::Kusama; - type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; - type HeadersToKeep = RelayChainHeadersToKeep; - type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo; -} - -/// Add parachain bridge pallet to track Kusama BridgeHub parachain. -pub type BridgeParachainKusamaInstance = pallet_bridge_parachains::Instance1; -impl pallet_bridge_parachains::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::pallet_bridge_parachains::WeightInfo; - type BridgesGrandpaPalletInstance = BridgeGrandpaKusamaInstance; - type ParasPalletName = ParachainPalletNameAtKusama; - type ParaStoredHeaderDataBuilder = - SingleParaStoredHeaderDataBuilder; - type HeadsToKeep = ParachainHeadsToKeep; - type MaxParaHeadDataSize = MaxParaHeadDataSize; -} - -/// Allows collect and claim rewards for relayers. -impl pallet_bridge_relayers::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Reward = Balance; - type PaymentProcedure = - bp_relayers::PayRewardFromAccount, AccountId>; - type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< - AccountId, - BlockNumber, - Balances, - RelayerStakeReserveId, - RequiredStakeForStakeAndSlash, - RelayerStakeLease, - >; - type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; -} - -/// Add XCM messages support for exchanging messages with BridgeHubKusama. -pub type WithBridgeHubKusamaMessagesInstance = pallet_bridge_messages::Instance1; -impl pallet_bridge_messages::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::pallet_bridge_messages::WeightInfo; - type BridgedChainId = BridgeHubKusamaChainId; - type ActiveOutboundLanes = ActiveOutboundLanesToBridgeHubKusama; - type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; - type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - - type MaximalOutboundPayloadSize = ToBridgeHubKusamaMaximalOutboundPayloadSize; - type OutboundPayload = XcmAsPlainPayload; - - type InboundPayload = XcmAsPlainPayload; - type InboundRelayer = AccountId; - type DeliveryPayments = (); - - type TargetHeaderChain = TargetHeaderChainAdapter; - type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - WithBridgeHubKusamaMessagesInstance, - DeliveryRewardInBalance, - >; - - type SourceHeaderChain = SourceHeaderChainAdapter; - type MessageDispatch = XcmBlobMessageDispatch< - FromKusamaMessageBlobDispatcher, - Self::WeightInfo, - cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider< - AssetHubPolkadotParaId, - Runtime, - >, - >; - type OnMessagesDelivered = OnMessagesDeliveredFromKusama; -} - -/// Proof of messages, coming from Kusama. -pub type FromKusamaBridgeHubMessagesProof = - FromBridgedChainMessagesProof; -/// Messages delivery proof for Polkadot Bridge Hub -> Kusama Bridge Hub messages. -pub type ToKusamaBridgeHubMessagesDeliveryProof = - FromBridgedChainMessagesDeliveryProof; - -/// Dispatches received XCM messages from Kusama BridgeHub. -type FromKusamaMessageBlobDispatcher = BridgeBlobDispatcher< - XcmRouter, - UniversalLocation, - BridgePolkadotToKusamaMessagesPalletInstance, ->; - -/// Export XCM messages to be relayed to the other side -pub type ToBridgeHubKusamaHaulBlobExporter = XcmOverBridgeHubKusama; -pub struct ToBridgeHubKusamaXcmBlobHauler; -impl XcmBlobHauler for ToBridgeHubKusamaXcmBlobHauler { - type Runtime = Runtime; - type MessagesInstance = WithBridgeHubKusamaMessagesInstance; - - type ToSourceChainSender = XcmRouter; - type CongestedMessage = bp_asset_hub_polkadot::CongestedMessage; - type UncongestedMessage = bp_asset_hub_polkadot::UncongestedMessage; -} - -/// Add support for the export and dispatch of XCM programs. -pub type XcmOverBridgeHubKusamaInstance = pallet_xcm_bridge_hub::Instance1; -impl pallet_xcm_bridge_hub::Config for Runtime { - type UniversalLocation = UniversalLocation; - type BridgedNetwork = KusamaGlobalConsensusNetworkLocation; - type BridgeMessagesPalletInstance = WithBridgeHubKusamaMessagesInstance; - // `MessageExportPrice` is simply propagated to the inner `xcm_builder::HaulBlobExporter`, and - // we do not need or want to add any additional price for exporting here, as it is already - // covered by the measured weight of the `ExportMessage` instruction. - type MessageExportPrice = (); - type DestinationVersion = XcmVersionOfDestAndRemoteBridge; - type Lanes = ActiveLanes; - type LanesSupport = ToBridgeHubKusamaXcmBlobHauler; -} - -/// On messages delivered callback. -type OnMessagesDeliveredFromKusama = - XcmBlobHaulerAdapter; - -/// Messaging Bridge configuration for BridgeHubPolkadot -> BridgeHubKusama -pub struct WithBridgeHubKusamaMessageBridge; -impl MessageBridge for WithBridgeHubKusamaMessageBridge { - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = - bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; - type ThisChain = BridgeHubPolkadot; - type BridgedChain = BridgeHubKusama; - type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< - Runtime, - BridgeParachainKusamaInstance, - bp_bridge_hub_kusama::BridgeHubKusama, - >; -} - -/// Maximal outbound payload size of BridgeHubPolkadot -> BridgeHubKusama messages. -pub type ToBridgeHubKusamaMaximalOutboundPayloadSize = - messages::source::FromThisChainMaximalOutboundPayloadSize; - -/// BridgeHubKusama chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct BridgeHubKusama; - -impl UnderlyingChainProvider for BridgeHubKusama { - type Chain = bp_bridge_hub_kusama::BridgeHubKusama; -} - -impl messages::BridgedChainWithMessages for BridgeHubKusama {} - -/// BridgeHubPolkadot chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct BridgeHubPolkadot; - -impl UnderlyingChainProvider for BridgeHubPolkadot { - type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; -} - -impl ThisChainWithMessages for BridgeHubPolkadot { - type RuntimeOrigin = RuntimeOrigin; -} - -/// Signed extension that refunds relayers that are delivering messages from the Kusama parachain. -pub type RefundBridgeHubKusamaMessages = RefundSignedExtensionAdapter< - RefundBridgedParachainMessages< - Runtime, - RefundableParachain, - RefundableMessagesLane< - WithBridgeHubKusamaMessagesInstance, - AssetHubPolkadotToAssetHubKusamaMessagesLane, - >, - ActualFeeRefund, - PriorityBoostPerMessage, - StrRefundBridgeHubKusamaMessages, - >, ->; -bp_runtime::generate_static_str_provider!(RefundBridgeHubKusamaMessages); - -#[cfg(test)] -mod tests { - use super::*; - use bridge_runtime_common::{ - assert_complete_bridge_types, - integrity::{ - assert_complete_bridge_constants, check_message_lane_weights, - AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, - AssertCompleteBridgeConstants, - }, - }; - - /// Every additional message in the message delivery transaction boosts its priority. - /// So the priority of transaction with `N+1` messages is larger than priority of - /// transaction with `N` messages by the `PriorityBoostPerMessage`. - /// - /// Economically, it is an equivalent of adding tip to the transaction with `N` messages. - /// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip. - /// - /// We want this tip to be large enough (delivery transactions with more messages = less - /// operational costs and a faster bridge), so this value should be significant. - const FEE_BOOST_PER_MESSAGE: Balance = 2 * constants::currency::UNITS; - - #[test] - fn ensure_bridge_hub_polkadot_message_lane_weights_are_correct() { - check_message_lane_weights::< - bp_bridge_hub_polkadot::BridgeHubPolkadot, - Runtime, - WithBridgeHubKusamaMessagesInstance, - >( - bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE, - bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - true, - ); - } - - #[test] - fn ensure_bridge_integrity() { - assert_complete_bridge_types!( - runtime: Runtime, - with_bridged_chain_grandpa_instance: BridgeGrandpaKusamaInstance, - with_bridged_chain_messages_instance: WithBridgeHubKusamaMessagesInstance, - bridge: WithBridgeHubKusamaMessageBridge, - this_chain: bp_polkadot::Polkadot, - bridged_chain: bp_kusama::Kusama, - ); - - assert_complete_bridge_constants::< - Runtime, - BridgeGrandpaKusamaInstance, - WithBridgeHubKusamaMessagesInstance, - WithBridgeHubKusamaMessageBridge, - >(AssertCompleteBridgeConstants { - this_chain_constants: AssertChainConstants { - block_length: bp_bridge_hub_polkadot::BlockLength::get(), - block_weights: bp_bridge_hub_polkadot::BlockWeights::get(), - }, - messages_pallet_constants: AssertBridgeMessagesPalletConstants { - max_unrewarded_relayers_in_bridged_confirmation_tx: - bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - max_unconfirmed_messages_in_bridged_confirmation_tx: - bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - bridged_chain_id: bp_bridge_hub_kusama::BridgeHubKusama::ID, - }, - pallet_names: AssertBridgePalletNames { - with_this_chain_messages_pallet_name: - bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME, - with_bridged_chain_grandpa_pallet_name: bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME, - with_bridged_chain_messages_pallet_name: - bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME, - }, - }); - - bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< - Runtime, - WithBridgeHubKusamaMessagesInstance, - PriorityBoostPerMessage, - >(FEE_BOOST_PER_MESSAGE); - - assert_eq!( - BridgePolkadotToKusamaMessagesPalletInstance::get(), - Into::::into(PalletInstance( - bp_bridge_hub_polkadot::WITH_BRIDGE_POLKADOT_TO_KUSAMA_MESSAGES_PALLET_INDEX - )) - ); - - assert!(BridgeHubKusamaLocation::get() - .starts_with(&KusamaGlobalConsensusNetworkLocation::get())); - } -} diff --git a/system-parachains/bridge-hub-paseo/src/bridge_to_kusama_unstuck.rs b/system-parachains/bridge-hub-paseo/src/bridge_to_kusama_unstuck.rs deleted file mode 100644 index 0f6bf7c..0000000 --- a/system-parachains/bridge-hub-paseo/src/bridge_to_kusama_unstuck.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Cumulus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Cumulus. If not, see . - -use crate::{ - bridge_to_kusama_config::BridgeGrandpaKusamaInstance, weights::RocksDbWeight, Runtime, -}; -use bp_header_chain::GrandpaConsensusLogReader; -use codec::Decode; -use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; -use pallet_bridge_grandpa::{BestFinalized, CurrentAuthoritySet, StoredAuthoritySet}; - -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; -#[cfg(feature = "try-runtime")] -use sp_std::prelude::*; - -const LOG_TARGET: &str = "runtime::bridge::migration"; - -/// Number of best Kusama header #22780167 known to Polkadot BH. -const KUSAMA_HEADER_NUMBER: bp_kusama::BlockNumber = 22_780_167; -/// Kusama header #22780167 that enacts new authorities set. -const KUSAMA_HEADER_22780167: [u8; 113444] = hex_literal::hex!("0fea7782cc693658a5a89a59e238548009fb0b67319be7c8333d23ff810ce4c91e646e05dfa118464bd9cf6ea88cc945e8a0a316136a50b126680f4a31b15250ee19ef6280aefc4fcda7a09500fc997235da1469b80769f11871c96ee4fd9b4dd76135d0240642414245b501030c0100001754051100000000be38c10f73f74bdc03a5dbfa985510cf233785fc2501f37bb4b370c695ec7942395852e187b4170cb9fd5b7e3fa220e296d87898bbf658b6ca03d4268b64b30ab7820fe3a7b7a62d766657ea57d8843c67bb589bc5d1d1d96628e844ac99d5040446524e4b2403a50300000000000004424142451402a503000004424545461402a503000004424142458e71020001a10f1a970c0087e6a4f83dd3be864030659e38e0982f1b94e6bc3b63565e2feb49720100000000000000ec1e2714701dc1cbc272939c622e7b9fd73e0478fdac925cf779d92e7db516440100000000000000e822f63f9d78c311868d804cd4f14da1d01caac726d1f081cb2e98854bba9e55010000000000000016d06cd97ce36de99a92a5c6093191c0d6cc86adc064386968bb1100f189337e010000000000000006563861e2f1e6ec306df8ae4e71630ddfeefd12824de9e06577a7412543a34101000000000000003ad32b11ce7aaf934ba9c4418a3814bdeef330f16cec8783f427f358b1fbf36d0100000000000000f047343881d511661151e80dd7bb3ac3e96ae1731f76a55296821462e1670e510100000000000000186156b372212bf8c551c23d83d5b1e173090da443dc00f79e5ea80600dbb1320100000000000000b4e673fd260c180aaa745bb24b29dc88f28fd0c170efd9a9aeda7243e051046301000000000000003258a13e70613532e393e0d011fa7cbfbd64395d53d5ba393f49ec76fab1d8420100000000000000786f18f05ea0be71339daa14031a9517e8ea21664b26fdfe232fb84404cad2040100000000000000d2ee94cdd2b4209412ad8989d8c1e6852f2690a53204103ff3d272b7daa56a7e0100000000000000b89e7612db8e79e552ff6698feabbc4114f53d5de71f3ee251793ef952ffb550010000000000000060521ac931b0f7ad583ad4bf993a3eeecab1960c820a5a0c0aef63286160cf0a0100000000000000f4cff905f239539949e769eeb212f22ba2bb01a4f08b3c24b809a36d3fa1d5730100000000000000c674821b26b1c95d9ec6b1f0ae86d774267261de72a9f745f3ab13b4d9f5603401000000000000005826355828606dd689db2a3d20e18a751df8960ea2fa86b8a1de3f7ae360472101000000000000001892dc63cbd0d3d07f6c05e9d3c2159beba65135d85d23d7d56bb973fe3515340100000000000000768f4b5b7356f20e136db988fd11a2446b699162d73d3afe810b7934634167260100000000000000e8f79e624c673959af1ed13642c5430d6f11d4b651a31b8d03c5d93aa402ce19010000000000000034d0742229ec2f1690b85b7e12b3e37b6840a652e52bf0420a51f696ba406a47010000000000000020590a5950f9f4371d799d0c033de53fd3f20d4479a01935c076fd544c90f86901000000000000005e74d90dd567ba4e439b9ced47a11d5985edcc728bcf779e152d82d87d55d45e0100000000000000a85ff25581abe911021a89410565f6bc2f7a5ed106b9c5a1efc0f278e3ccbe050100000000000000d0a5191336af2103c8a0809e40c09ee5c4f56357f9103a22438785e695b72765010000000000000062391234e5b71a3a5456fd366640be6da72bf58b3675b22daa9eac64171d66030100000000000000bcf8a85665dd8452ffc6eb3e9d2168c0ae31c9bd08efbd3b2517da8c6018ea630100000000000000060b1dc3e1709ba7d4a8249db4bb41864defe535193504673721660e1bc48b0e0100000000000000ece67affcd525905f696dc3d10a530ad4d174d63d149afda506d58186824d04701000000000000007842de634b369f1c9b0f2d8b992f741813a56256b4432f35776a4ec8d185804101000000000000004870b5128bc8fb0deff2fe20df2243ec9028d0d3e96d93d0486a3cebd38fa12101000000000000009020f486f46911d43acd6bf62c33c1c89a390d1a6c1dc019f13072eaf3d193180100000000000000fa4d26116689b2a145d1c2b0eb4c7cd5516520161bbc211b66a2c81ff6156b0901000000000000003e67bad9ffade7c6c9c352d4e51fde629876d9e2b5e3bc48587df3b4ef833f2b0100000000000000c63810591a73eedfb2c57a0adde5795d5dc865defc9ce5b42d4d80faad45282e0100000000000000a6d0374fb5171d7640990763aea4f0646ccc504f7575b66146caf5ce350d90150100000000000000c86a78138a57b9b5094b1fc3ab898988d558ea4f3d4369d22d03966f7cadb16e01000000000000000059dba0c599635a16f933ef674bb70bcb1edd0c90b40ec9997cfca6029571340100000000000000269b08505c1206d1574bfa8d8d519690e7262c66f6c8e283a65f895cc32c930d010000000000000030ed0bb7e681a98eb1351d2f12208009bc5b55d173f2a5675de1933a2c4f88470100000000000000cc77bc087c5ff4d248fbfbbb1cfb73c6eac030c670ac3e150a09309ce1fd487801000000000000009c4a8b40e96f064701043a01b704349751e1333084e7f3eb1d0ec084633b030b0100000000000000b4dd17bc0582f5ff1dad7553867974ababd960f5c950bd0bbe7ac3c0699a994a0100000000000000f8dd1d8bbf0a82247b7c972aa1b38ac83cacb3f9c835d38275bfb9926cb94158010000000000000052e402a1bff5d11b1711d22be576423f254f08c6d804b9a8c4f8abe4cd61684101000000000000000856b87691cef45b198452cf4ef615cb444b5d0d64eb4fd6a5d1d64d014ff3110100000000000000683a6557a6ea6029cd4160894298ceb99e23e18486879dff716abac6d1c9ed700100000000000000aa54aad4e4d13417227988dcd9c9a168b8874e5a31275e96862a7e2ead0ab7630100000000000000626a33f25715f26ff7d9757df553cf7a998e094a1f83405ac0603f89947bcd15010000000000000076e3be7c201cf82cef1dd115580087e5ae1eaba509360fdabd8f03f12118b7470100000000000000446d246be98b35cd826eb4db1c7dd08ba71aa2cf31cbd864207ab62c1b04ca210100000000000000aaba8a588bfa17a6f17d032a589d1de55da54afdaa13de13a88cdc9e645dee7f0100000000000000b65c2b62fd77efd814935dcb83ceffeec5672dc35738cd6574d86ac9619ea20101000000000000006a4f8fa5aa2fee2b5fcc7a5098002f3cb3e74db6ed265dd536189f9c05a42e190100000000000000c682ed5ff78d220f48291b64ce0f183e6c68a23de99c8573ff673ea4f2faeb7f0100000000000000c629cb0a7854f7751378c6a9224e338ffc3fa741860b5255c12841a7a83842440100000000000000a6eecb94e084e407406a6489882b00d75bacb4fe9f65083a58417debb90d04500100000000000000bed8b1b99e4770feb123eb13bf7f8a18175b09da6f50efdc9eeb0d043614686f0100000000000000940fdd53e57ca468bd7a4cf6a0e034317db60dc06f7de5c2701533bac03ce4580100000000000000165f5c92eb3d7d580789cb7f729612c9f74aa0be4e44f8f0b3abfa3582519c3d010000000000000090693154fe4b91eb83d308b9bd90765885bd82667c02dba50c67bc460488b4110100000000000000f8bfc47cedac628c69417546e448af9c3fe6a1396961e3dca4fcc03f78e22863010000000000000046f03994e53752e6f528d5775d56b11dcde950e6549262faa5ce586ec53be7220100000000000000f46fba5129196f64415ce78944a7ef7c17b99928065e483d2d5d9afcbb3b705101000000000000000ee19c0d14da0f6964687d3da35ecabce73d4edaaadd09d3625b5cc31195ea650100000000000000946410ae4c1375f136b2e112579fc0d00e5083a5bda9fa36d05d28d7417daf2101000000000000000a0da83453491f88599c8b9bca602097a46f378c213fc1d03bbeed68254ef06201000000000000007cb73489133b0c49bce2da3be157cf8a17496081f0e2fb869456ffb7c3d3380401000000000000005cf1dfc90cbc38a826f4eaa3c837a5766adcbf842ac925cd44d401e7102ee7280100000000000000d206fd2016c30fcb03110f2bb479d5bde7acd8f89ba8d7f598fea74292e11d5501000000000000006487460f041de663158e03ad27189f334e3f497400626753eb7391c37e5e861501000000000000006eac6786ae56ade4cf9927e9adbcbf608c32b31ec3c5142fb1da4165edfa1957010000000000000098f2c8d94f1d7ecda8c2f526ac60be8e6e4cbaffd26c0eba1ed8c16aba3ff10601000000000000005641b8983a487fc8d4bed7bfdba059f5bc351ccfbe14b216aa36aa209162222601000000000000003a0caf3f66a7dbaf9c7250810a66baa33cb8094c47f7797ad5eb239e55b7326701000000000000000810864445fea52648fc0d0ed956c21ff2ba17100d27c50ad25d8ecb9c6f7a64010000000000000070599f60d516be2fd05f5f71df1aa9bc91cd4688a66dcb4723d46c18549487750100000000000000263e35413f5d9be66dbdfdb2de58e0b5e12961a71b4c1b2769e0b3344c932a50010000000000000084fc10a0bd853a319bc3c95ba668186ba8e2de7730dbdbaa0fc9d79fc721451b01000000000000003c5a3e0c7d5d2c163dc20475cd8d2410446d88a927c3161d75c804fd7195237601000000000000004ec9c5432fc1870e0bf9f45d28b7f25ad0fe5064311588e72b2df761e4f06165010000000000000060f3d9fac368e530f016a30a4d0638abd9e9c6e760aad4e8780a15d750221f65010000000000000018f0ef0bcc5973db205a90c5e071421a157ffa6706a4db4192a7f12fa98f935a0100000000000000a20db191e5f778efe1a9baf371b73b957a16aa7792fdfb17d09c73da61e03a1301000000000000009e2bfa20e0fdea2e167baeafb3ebc4a7547bb7b819fafecf2db997b9cd94d1490100000000000000d43b6dd18bf30df0ea2edaa425ece4a5cc71a343665fb2d39ebf3fb18478d54c0100000000000000c403402292ed18f297b6c523209595e8018a05a49489e8cab81b99bb04ddbd0e010000000000000064a3fb0217f8d749e0a240a5623de8bf1d804033da1acdf03f02665044f0c159010000000000000060776bd1c77d88b9d62c62b1674f07a179a10a17044c1691b35afa278c7976720100000000000000fefb2e58137a892c6357c7bc2e00208eab60a1861a98bed54c91fe1bcdcb644f01000000000000003cf87216d7e48e0a92e21d9ace02918e6f81472ecaec4cb4e5b5504e8d83b220010000000000000094b473e9d2d5ebe6bc099f357e1d90d59fd8a6d8301b9bc7483a93f64229e75101000000000000009e224c89083ed1bd783cb7f4ed522aa3791817e3a4fd01d827e36281e32c14150100000000000000a836d97898b958f521cde8fd418941d3f377549648d9079d85478de0743d571e0100000000000000de30763310f322e093736a336ff8466f500c6ddfc32c1c17898e4605fb99f2610100000000000000487a1dfd2b174df55d13e95156ef89f4829e69d3a953bc8d86967af518352a57010000000000000024a9a17cc0a2234785919109701779803aac6056c0c9f9664b7586867d66352e010000000000000008e092c8e65b307e97634399a58cfa0fa04507bc39f8ec20989e1ab8ee9acb2201000000000000000a05909d4e754ab732e1a81f145adb91e0475bf7a6771c10bec263324de50b0401000000000000003c80c6fce9198044bad1849661d3c1a4bbd8f5df117e5972ece7873da3d4441701000000000000001aff282613ff835dcc9b33a3817b2edfcaa8dc0dcc5df387547fb2cc1f30251301000000000000002c470f4fd79f7c39c511f8557cfa19c83bd17940d391db41efb2dcb43702b3770100000000000000e64623cf1e9689b21e7d5ffced5f8de5f98cebe1f35b3b888655f853d07eda33010000000000000066e4ec20e86393ee5236bb6118adeb1a23012f849c04b4c49e3969e1052e6c070100000000000000945dc1b3821e64e86a297a74a4c9b572025393af0e5f2b178e25d0619d1b48390100000000000000588da8b8bb783b5aef977c27f12da55fce1517779f318f61448386bbdd29f72a0100000000000000465937ba88ff71ada7353d808fa51698fd36d1cc38b9ffddc1a4baca8400ed7a010000000000000040cb7a58b95e5ae40182399c9671c4dbaaf68cb4ea0f5071e506cebdc9c06e0e0100000000000000360bd934a82149076d1f91fbd744642d807ab8a2e65f9e1e7972496344ca38140100000000000000ee5efc6f1834d40479e00cb2c0ff7f1cae5cd4250a02cc1e17e4e133cfe51f0d0100000000000000d0f46aa7497818bd876a8124bf3f23274a666bc1fb909c2eac0f16cc14719d140100000000000000a2ea5d575e3b87b392df021a6b0df785b432e17e6b48b5796787b37d61567a6701000000000000006ce85b19772fc068121494528478b92dee4834adc57bddcd35f6b0a531eca1240100000000000000b0280c6378422321879c095746a0c3d509a1eeae1ea2bd5e2b2db86627d0d43d0100000000000000fcd2d53fab025f909f9989008799ad8cfa8f236fac1673fd0915243619cc124401000000000000005eca392c73b85d4a8a77eaa5c241e95ae8c344462d345ae43a883d6882d3070c0100000000000000f6a96f4b9b6c70177b0365b207da82bfe4c2033f52c2d6c44b36f6570d1677240100000000000000ee8e500bbb87fd9cae37b8ca4d76b9608abd25fc4090800d99a6d4d60977323e01000000000000001cc29d5ca8f465c051246d7b55f5903f54fbe2573a083e60225c41008d010a7d0100000000000000c4fa3b6417b280c309e7a44aee891a24181774cc6f79c8739e3f15364586ff56010000000000000036d178c3b4295b96f4cd25b927e9981a16cf945cead51521b4875c065d84d36f0100000000000000f4d1721a01b1a8c2e45b551c6552a16559786c1eef3e57f46384c17a2cff98410100000000000000ac89c183c34ddf7d92c4335445101b5407f56fdcdb2905e4dcab66ff2f52534c0100000000000000b4374a602cf228a7fd9ecb13d5a2d1dde672112c5b9158e1bffda18693770a5d01000000000000009a79ed2037871ff18bc9568f51374a0f7cd58d1befacf93c88401b074a18fd51010000000000000096377488a08174948cc783e4ff708945d848aac15b1bf51ced4b54e34a8081280100000000000000143947427c518a58f34dd2241dedfc6bd89f88fd57d2ee59f695fe61e6df330e0100000000000000005530346bfa7d0e27a1bc64c8fda7ef5485bb89e9cdc99fa3717118026248260100000000000000843750a91059689e3a795e6fc470cb8c0677223c8d70cddc8224f8cb5f0b0a4f01000000000000008e48e242f0427ac1a9fd2fc0b51ce813ee0661dfb945884d7d29f8af6021132a0100000000000000a4a751d0ae63719eb0dd129e14b4f36e34634551c40f66763a6c0b9473edef3901000000000000007e37ef0fca7c9f761d9ab5932d3833dfc93f710e82671156e7f412e700085918010000000000000050a35c5f787200244adab8b877cc7d1ee8472b4b6c80b08f894a5b32485bc60201000000000000006c476d52fdf95a9a95ea3fb1fe788ecdf7ddc5570fce862c4f32066e8d05ba1101000000000000006a5f83b29c7502cd757e037cf9fe4a19db2d82fe925a5befdb0bef84347da3030100000000000000ae3d938f7f0ef7a97865ab399e3386a014141028eb2e0b3242ae2275ff8d842f0100000000000000bab5813abb401aded6ec43d8f5e5514d96ec087611ab134ef3557164f28190690100000000000000869502b50d6fcf6a015d2f401d161f63aed195657e3e7c1c51178924d487002f0100000000000000b456207968746cb78bcbb88077a84d444cd536a1557039bb5a5c8c71aee3561b010000000000000034c78c70c4667bc01d4097c27d42db778e4c666d60093892d2c5a2a6455c362501000000000000007297a7c0f5068e6badd88a8d58f1207012f19dd47dbf5eb5b2a8b612697f526f0100000000000000e4a4fa9ad0f9c7e01cef99017e92a39c95f67254bcdbd59b2554e492a90bca730100000000000000be35cad77f750b0c377a5a506507c0b92284490d468d66751dc1b48cfa501a1301000000000000000ee98b3b98d782c550599539c1add8b0ce769c618edb1fe5aa7a6d8287e8e445010000000000000096361f770d0e25ec6a6e2d442908090ab183f7c0f6c2c87e6a6b224dbd7d027a010000000000000004fa2cd531eaa2dc2d54bb98751aadd7f2a76988cc8d2aae37eaa78c3ff28f610100000000000000bce99e3f6502900250732031e04063e3eb15f924c4c58908d0a8cd0104e567570100000000000000a02fb8c585b52bb0f2cdc2c8018a3c474a2a35431c3f470b7352333adec4671101000000000000005c60da13a5a5e97065fe691345213fed7499f5691e820b48ad1af4a0ebc4e97e01000000000000005400aab2360fa71ccb1f79b69a5ce64de0d420b1eb0eb34a0a3c903c172e9d740100000000000000d201838d97ea039077a2e5df2f25ae6e2742f7fd4cf23b18854e70e3774768230100000000000000f2f6e7d4c8adc6a8df61e989a64584efcbc4cc1d97a94fd89da412109d42012401000000000000008c93541f5c659dbb2c5e6173df63cc39ecaadcee68150925eb8ced5f02c90a4701000000000000002ac82e0a6dee9629a2eed2e8f4e65a0a4697541bd7c3d551163a03d472f76916010000000000000054fa4a0c57eecbe50d39996e827016839621ddea0061dcf08cc35dea36070b400100000000000000b648341bc5ee83ccb528e31f20481286d0d406de9129a364ff1bb5caf9a8d5720100000000000000969e6bb9058e1375e19fa710c7baf2a327f5c1aeee303792e2c42bbdd2efb36c010000000000000040337975b3322951e9ebc2e1a590e94f501cd69824c6d1d30f6ff38eecd26d120100000000000000dea467639b1473602369ce00c018fa7f0c85a23e6cc4bb02ace50ac65b1ff47701000000000000004c8854e27a24460de6097bc11e9f3979759882dbd874eaf4209d1d1a1fd9d8060100000000000000742ec8e0e87f674bb02515e196cd71a5a583ee9880aa495db3548e2c606f026e0100000000000000521288566384610a2ba0f5d427e7aa59a242065147979b0fa1fd7c7bde62053c010000000000000048c37f31c325d29369199d8898160d309ffe00210947c7e9152e79ef9b8ec97201000000000000000ec136ac0981acf780f272dbac58eb564de4db3120dbe5f7b8f170cd308623210100000000000000666e2028e3bd8a249eba4b99b6c5eb8890eedc696a9d6b679826542fe9073e280100000000000000c662888a2659cf232252d22a32c167b10fb4d361bc58d95b54a4f1dc76266a38010000000000000082ece8ce65ed0b289ee102852c083d05a1e93ab2b2a54a660c15e23189ad9c010100000000000000f4d4adc47a7abbcd1be57217b7427680399968a111cbe262786850997cd3a3700100000000000000b071f29f244b53e6d05fff6430b7cf9e1536de9a3baa2d78e324cc7b7f17353d010000000000000020400165d85e013698a2b0e9ca98d491ab37983d3d632b2d9d3f4bb3d03ad2140100000000000000d20794d62e2485c64065c0a75ecc7a0e622d2b70f293e774a228db6444c6921b0100000000000000e6ffb8593c005d9bdf1bbb2e640199ab909a879724eb96ef580b05b4c150280201000000000000008864b55c89914b2088bc4e5d1cea69e6cccf705454a0607b99a6261d651a9725010000000000000050d9adcdc8786b531540d05a910d27a0a10dc237ff68cd9a4fe4023d0fe5d53b010000000000000008bd7193e3e257191d43de603817acc90c7bc4e51828fd2da659ea9db7a2d34a01000000000000003ecb9d9af67487d527878934296adec5e2b2dcf8aadae518be3876abd0a77e1c01000000000000004e9881d84deb63c6b066565be351c84463ebebb4ac6489e0dae38ff8572aa36b0100000000000000eedb3647cbb0a091f55e231cd8dff5ee1c120752e040f0ca480d75ec82a6f2640100000000000000dec0963ca4d3fff5eb255aa1300ed9b782d48c60f3f391a2425575c64163b35401000000000000000c01813f0449b65a4e22d529657e35ad2d4ee4630b2b28755a8eff933b301c2b010000000000000014e9c1b77d7149cb8d3c5cd869d144087a6390a8cab5c440bc7f1a3b582e725c01000000000000008ed4c0dcc09ea53645833b075af6b7642ed5b79f84295a14e85c01a4bfa0c40d0100000000000000e44e27a390f1f3a786af28571714a9c9138014abfbed46dbca0eb469c8edc76d0100000000000000c0c5d30974707df28794c58722fd01bb784e914187909b607d965c946d80da2601000000000000001a2095e38cc5469101da9a77f6271ecc977c56cdb3a1530539a9156efb20a4740100000000000000d2d18f7d7a17c93ec66d44845dd418327101352b5f5e0e4aa43549099431d5590100000000000000647ed8aa38fb4a185dda46e4f2d5b43c7f4fb61b63c0d9c38d5eadfd5c86bd1b0100000000000000e28d29f04baf119a057b82ac08e704b3de7a72f074db72ba008c85d50d950d4601000000000000001c73141dd130ca288f63558323ea68183e2971416dd1befcfeab7e0e37356d5001000000000000000cb028a8c36a8319a6167dd8152f657986d68a584a2fe15347893197a387e32801000000000000003845aac4d574b6db82135035f65012838200fcbf70dcd2669b4eb2feee8b046401000000000000002c9137207890a61fbe8457b959abc279b3f6e3c97b1312cd866e76d6a0b71b100100000000000000404c484dfb30b55a573d823fd5429a7c7e8bc3816d08f6337964f4d766b26b4501000000000000000631b8542fb8f52af205996198d987bbccec564dfa4821169e53528d988c91300100000000000000a4755f915bee0f41eed47d8a2e24d460432dba2714f5e46b46233e61146fd0660100000000000000f84d7d86b5313a034695f96c392559180aa844ac8891a5b971b2215378b6fa2f0100000000000000c68979829e21e2aa37e32b36e7f6603cc4d25cd5973fb9daf59a0301e37101410100000000000000106209f3966445fecf0d1659f08affbb36dd1bf4cb9cd0511e040d78783388460100000000000000fe6421985878b1c8892de32550508f10d9a5178b81c4d07e6ddbf67ac522b60b01000000000000006cbff9f20a267acc52265d5fff98b1d2d257588fd0caf0a51f9e80408fed2f0a01000000000000003ecc3b44b0af325b79dd55253e9ea778581d135385fba766876c127c7531ce380100000000000000faeb3de75e9dcbed57c2eec50f6bebdba16d29f5810a17170e81876dab71a36e0100000000000000f89f408bc2301c1e5436618f4584d88c4f2f8bcab87f0ca6d553d648698cd44c0100000000000000ce0e8b2c47483d5110640cb5663ee2195304be8867fd062aefeed114a7545a71010000000000000074210433ec669aee4423741e4910d0342c671267a04dad2e2dff9b68563bcf2d01000000000000001adb97e676335b401bc3793f1ba9d46377aebcad3fe43e7021b702cf874fa25b0100000000000000904b4353405219479206ba30fb2a5fc4f355b1afa89c7b75b453cc318712b96e0100000000000000eadf745fbd8707e65c88345fce0fed443d1970d182ba6d921974dd0a14d26379010000000000000062aeba6c00add54aad44acf0b6ff74deab608fb4050860b4ddc4c1cda2acfb7e01000000000000008a73c1b13a2fc7d7b71935ab3000df76cf8452f5889a620f2ab1903809960346010000000000000068004af803c7de3d8af4f5f00aa2a355d2bec91c7ad520fe37f3f7ee44ea121c0100000000000000a07d3d200075f2268d962f1c3d5beaab819f4b0801927e050c87ac7bfe96242e01000000000000003cba118380457e6595c92daa9273a85b479a6978331565085cc07cb9b6e4e54101000000000000005442b0041bcdd067307dfdb039a5328a9522c589c9f74514bbd30e077eddff0201000000000000000ced56c088a4c4bbaa869fd9155e244efb7c3ca17babe98bffdde7c1baaf9e4c0100000000000000685225ca8de03a1e63129ed3e27b002523a9a69be297a2cee56e4d41dce27a690100000000000000a607ba414375422f6d1c1020934f03775ece5da96eb30ea1827dba176ec14e140100000000000000bcee489a593a6184713650ca8bb3c8ebfd28e20e0ad1566ecf2c65f852e52f380100000000000000aced385f2394514716315331247b963243dc0719e274d93e07c1499b23e8ef7a01000000000000003c71dc4887c81197589fd793f54d9599d68ec9d82e536365b53d348a42f6a06e01000000000000005a3cd692707c6b7015f66db298144424039f82a0c80274f6f651aa6f092697690100000000000000a615cb1807e19b74cb871e43ab43b988bf288d9a87f755ddef498bc97570066501000000000000006acd8400ec0c7fc408472dd2de16233831419f919a012aab08bf0e2d42500b780100000000000000484c16cca940b72af0466559458ae1d73122778663c2c09a83f711c90314895401000000000000004e55663cd745c4882afca18caa516bf7ae0599d205d85d532f55987b5eecfd7a01000000000000009cf2d4beefd100e72ecedbc263e8d908592276cc98c8df9abc774b4f428c8a600100000000000000ded46739e6ba5969bd1e2d00735b7a793a62092cb4d5eb7812ec4d7c20f4780801000000000000004e6a38f8189b3e5b8989c73336101edff5d7e8db3e87214f4d0e558207e1fa5a010000000000000048e2b0533bd9cb3dc85a887217ffd62353613af3be09e146a3c97bc633b37e030100000000000000e661b385abb8566ad2888eda3a647959ca6931f00e6bbf920b2061cf7a8954600100000000000000868485a529de3ec059e73e81afa3a1d21ae3cc653517c2e8c78a647cb392b41e0100000000000000c85f0693dbc85be561d64ae3a56eb861477eb15d7cd1392ec7c24f236075e9070100000000000000ca0bec50cbac143c15dcec2fe57338e8833f2204eca85169925db50df07b12010100000000000000a8fd1f5982be500c6e2c77eaddb88c29b11e7c24ce228ac0097b2b2b37182308010000000000000006308826929897358de886764ae5a8141d6f8f3d763cb4c9a4bc4bdf9918bf4901000000000000007ec1891884238a7510b16192f18a6de89c0d7044082d4af89649e032dc2a94180100000000000000b8e042a65841d0002e1cc5f570224e239040aa6c66e485f7f811850c69914c1e01000000000000004a468b10340c0d1a7db26c4f1c48df10658da511ef29c97a941e09028fa098290100000000000000023c1119c45c0ed502145f3f4611864e2c14c448df05239588e1d0e41a990d320100000000000000286b843b13cb1eca1599593a566b648411a2aa45a7796d79b13ab6e4f07f3c5a0100000000000000aca2a5ed66685729657594af90b31a6353834e69664757659df87713442ab51501000000000000009c3ea31adaeb3e0c563991218fd076581c97355f7576fa354312958b63962d400100000000000000f2a421fbaafab0d7947d976770b4fa92a456f74f0d769a3bddc68656610a6165010000000000000052aa69a21dc118042213a5dc695034a769660d0c964722458fdebad0817f017301000000000000009e62cdaa070364c33854e561f60896079e7b3564ec52fbbdcc0de7f898b5cc79010000000000000032a7c27e6c010f1211e16cfd4399280a980e070e642fb41e806c7f2c33fb7b2b010000000000000014c7e9e27d8c132e3c62e0d4c1b04c2fce6a1697775f2851a8a745e4c0a1516b010000000000000026f2f3c5e3c2c17ed392a4ab7889893086cf02775f2db7cf01c11570e21e247d0100000000000000ea61abea5cb017ad8db4e82806b10af5089452796ef3e1c3f47ee90aadfea16a0100000000000000125b8b9f9545c4c5892d96bb4b55c588e7e347c52a99f0db3609018f10f5e0080100000000000000b27943cf918d917063e8e14041b6152265f87d201dc4c79e02bbcd58547b3e110100000000000000845b062fd9fba836f3faebe12dabec8940c423b28491328cd2fbe2e8ab67d70b01000000000000009484ba17e8bee1c82777b34879922ee4ffd74aecce6cc9934fca15c1dbf68c570100000000000000404efacd41789aa8ff8b476696ae59cd522ca1151865ef1d88933e68544f3e3e010000000000000066e1eba6ed62866738d474842d46d8bdab9aa5e6f44d84de8ec5c4f4cf4926440100000000000000b85391d7db0428753b765faace7eaabc220e49843fd62cb5f123fe4b3ab6ef0801000000000000003c3305035dbf012f48ae15a733fc3aed23b9651f8d8e5fcf534da86629009b4c0100000000000000c0c1181b7ff4ed2cd9a173aaef4c49385212ba9d63b1dc0eaebdc811375e725601000000000000008a204af952cd14dfe00aae019de37d052de93ac489733e74a0b9a9cdfbee3440010000000000000054195589ff609f1084d5c4e4ff4d80101f6c1a1c5343abc845d1ec65eba28e0a010000000000000068154efe0e125e311f8280a39bdff123b89779141a3b22c4a8033b2c6822573f01000000000000001ea9521e1704d8c152393c32cb9add5482283c78afcc605d6686e3a93446227d0100000000000000146bf667f1d65ae1461ab5cb9344a9612637a03bdb2a5e335674f3d9f9852d200100000000000000e8234fec3fca9fcc21c925ea521456c847295bd437d5123c0c3303613e73bf010100000000000000f6da139df8d2b59de383b6c94c469b9e0d0add842aceb786a074f47b8392844c0100000000000000d4262be21b125d4713e6b94647cf656e97f9875cc71f218d6952b55e4548a6500100000000000000960307ae3ead21dd4e763d390dadf66e91f47e57a9ce27db37b4c74c177d6958010000000000000060ccc22b5dea9eb4ab26582e95d97b2a0862d24c2daab8603b006a3ca0e825340100000000000000b872526f3d720d3555a150f04e91058f9c8c348e59714b98596eef088ba6727101000000000000005041cc3c246839c4cd1bc9dc2b701df6cfbbb60c8fb3a5e5515d6d1ef2cb5f16010000000000000002bb21cbe32f4da04e175f9a8f0b763c671626bb4ad1d72ce0482f7c88aed306010000000000000068edf883596adad12329a9cb07945afb8126343a749512314da0ab190eaf43150100000000000000d411df1d6f9c45a686a3bc5e802110c0be9a87936fbe2b4a87ec65062b415f630100000000000000a893451188e566836f7b87cdeae46b1c74331c50d42b69f49292ddce41fae149010000000000000002677c19e3b3a244664782195f0bc4d4a828ec37d3cacdf5246005fc8bbc257d01000000000000007460bfa508852ce917d76195a19946fe82b40921f7a30c21dab9703b00a22d020100000000000000043b654a89e6f2eca5a611a611d2a406d44a26e1a60010c93c0410c336954177010000000000000092ef2a937f98f92a99040fbc1e556a2fc957d3b183f5539165eeab5b01cd89220100000000000000169e2e4642ef3ce0e9d1de05362a682be66cc061f75a703371a2a7df0c6d442e01000000000000006eb9863cd7d96d0bfc747681dff0cce9b522b728c2f5fad200bc2556f8ecdc6f0100000000000000c8f47c16a3a876845b3d7d7a74539bf7fca17dbe9d143dfd034e8c33f447cd270100000000000000742782d90b6d3aa90c0a49aae51f0b62b6a43d1053dc10ca6f05e65b713e2539010000000000000004a5e5c44c1f6dbb2f0fa6db5671ec9258a7cec22503e5a47f1cc507e5c42a2a0100000000000000b439f85622445ad6820ddfd146ee8e04069abe9afff198362b1ee2d7c4c3d47f0100000000000000eafc1a70f30a6594963dc2d20e6aac3a8f1789e32b19148cc2d6364d03622a5101000000000000007ac81fcc26b65c9b6cd43c7e08c950a68a2e394bede1d371bff41333787dd2350100000000000000b42402ef690148a6c57c58affd88cce151b06d2fcf62f1d628492feeb08ea64d0100000000000000f6127b05312894d8670489109553b710094f1874bd8979cd2304ccd17699416c0100000000000000c41ef61a46a74ed6cb25be7c77d98fb54f1e8286cfed19b596aa3143e84d786f0100000000000000689d9be549b2775db68f28cb22e0b68766fb589559bcbf35c7953e5f18629e1a0100000000000000ce9650eb96f67b2e9e1db5e2ab2501993788781cfdfee43c71c4696b8ff1fc710100000000000000023407bb2db1205742050ce3aa2b75a6a7cf6ba36f84d341b96b343abbefb0000100000000000000ec3060b4505ecfd8c1c8ccce99f923415600a0d64311e17398ad105f7d76fd0f01000000000000003681cfd0eb84bb04646bfb0e27c7d164ebb0dec4361b3fc4a3ab1df651024c6f010000000000000068185c29ae68d1e7a1fd3f968699f90a24a73a5242a13fc2f8c9db912ed8a32c0100000000000000ce6efd0c0a879fead817b1fd63cda8b44cdae94d979e0f46ade5d9def47ad11a0100000000000000e280c5ad7f495e9e90049293fb2ebdd9d3a0ba7072e23f30c75bad534f3ba96e0100000000000000224e511c39dd3730a13c8604567dd4e28b1268825ee4549e724bf25998fc81110100000000000000809e07525c095f4faf9d5e0eee4020aa8214641fb8acf0a4ceeb0f43420624530100000000000000ba70abb526f8cb206e2fd2693a6b630b665306e18d870b5739c22e71c88420010100000000000000f20edba0fa7194fdf5ea9c47f8930fc74ba91c77bff2dfac16a3c24564061c46010000000000000088b7de1f7dcc98730a5d58f9a607fc91ec49de09cf88ea214ae7fbc66595d7650100000000000000d4d14fb7861e5e86ebacfd1eb1019dc5dad7bc6e0135cbb2c61e8e000250b6600100000000000000b4bc965d1c62488575b64173c32b7e1a0fa3a73908e772623f0986c77ea1b51c0100000000000000f225628714dcb67448e3797bd2f4afcf9005cb41ac8fb08c0b48cb933c332277010000000000000006e2183dad0d33faba40d6f225cdbb62566e8f3dc7f84eee192d2a4127f972160100000000000000a07e78245f18898d71a4d63c631bbcb85e5a3066739838fe3edc06b097144079010000000000000016aaff88573ab72af9a486abb31949734ae58b39b747bd04996e58295566603d0100000000000000b0693aefb1255610481281b257557077f049b94582f1dbec9f63ec1c38c28a1901000000000000008c6b83b54852803c7a4c5ceacef66a8a93f6e97aa85a4aa81190b2a108ab405301000000000000002ced84b75322e3f32a07889f7621195b011b22aa30f35e4c5fca906066514c1f0100000000000000c6053720bb159d6443198e2df041ca1635a7587b0922076e29663af01941532f01000000000000003c99f77c5c6c33a3ddd0a335aee3b76b5f29ded541add0b805a687d92b7f275501000000000000008641da97237520860bd67ea54eb5835f961ce50f20bd57893460e8220e9b6f7b0100000000000000b6abd787bcec4daff7cbbedb43a85f4762ad7eff7832757558a41c995ab3c90e01000000000000009e44cba3d45eb6466283696d3eda7f561497c12101ee4c58dad2fff01744541601000000000000007a7c854c757f16731307151cc3c412c76462539b8c35e540265bf9dbcaa26f4b01000000000000002ce1df64598207a337115bdc2365a74a44844257b67dfd446178fed59747610201000000000000000c597918f9db37c897515c20949eba31a0bd815583a605518457fa390bc2095f010000000000000030394522101f02cb1821a380386253161b9c92d216bbf20b4e7fabc09f6bf00e0100000000000000da7d9fe1143667ea92e7ea2d1c8e81fc3cd6b1e549d761e19bace9ae38b4cb720100000000000000221b6390d4461598c9edb206d3b0ff0a0634b2e94163919db046c2d07d1693310100000000000000d6b50ba2570f52eebb7c18a871dd410538d6e66af0755193eeb0a684e612d060010000000000000046659af99539580d7bc45783d957b5a4b62727257309a92ce624651292f4864101000000000000004a4ac2d498d6710e313d3581f8c562e4ef104a305f4f3e502a9ddef9a2760b7a0100000000000000ca4fc78d6d5f791f5b39154fefb59a283ba9a288846e565842f2c42011e82c0301000000000000008e2889bc7ee709be3d9f4b0aaba09973d6aec159dc2c796c1bcd52d6070ece4c010000000000000064331dd2c2da74c5873e14952a793e4419a4264214ec06d7ff1261d65e353819010000000000000032ba9d6420f93b801d4685059a853131fef2439604310034890d6c079f15291b01000000000000008c45f591f396105347fe658cf13f44ee67bdd98c782d0c29404f87a13687b6590100000000000000642b7fed496844414bb2118f6823562d45bf49f243cfa57c7063200a47e0bc190100000000000000ecf604ab6bc2a12466fd1df20d4a909142c20e677aee2c25bb4822ff97b7a56801000000000000004ce5d4255e46b25c383dd3189cab3fe07b1351a915c9dea167454afed2fdb21b0100000000000000b66ad1b8d924c503db99bed0e304cb5744031b1d391a5b44678c30e98df1d0200100000000000000b47fb9634411751361ca4ae99bc837380f6c7da0975ed1b8ade8899be106496001000000000000005cd24a3858404a17a5ab9dd7da28a6d77561eb2550d471b2e6e9ed2e6adf65410100000000000000742197142dfe414b411f5c6d27c1d7dca3ef6e9e34f790112b7ac768349101340100000000000000cef351144ab5671af7864b35d691e5a39f3ed3c22da4514b0b957b0b5d65dc1901000000000000005cd19af7250131053212feb4b094ed165c2b21c2ab0d6356db0e3bc522e583710100000000000000c218543350a14b06854d0b35a1bfdbeb1ea38896be48b08941be9d24bfbe9e72010000000000000092e5b998402d5fc09670de20ceb4758375765ba97b08c80dad1b29c871056e0501000000000000001e3f344e9e6312627104406fa90612ef1041b22d76e607592ac61c34b4c031530100000000000000381dd497927ab518705cc2c3e509792b1846d1f3fff07b6df81e95fc18328d7201000000000000004095c0d2aa1fad47aa157db613b012a680f21770819db38a2600e2c6c62b27360100000000000000aeebac9fdcf7aa2d76c22fb4f17cc7af3b68059a07e5f3691370cb05dac7483c0100000000000000aa182a4032f553d9b7c02b0eb97920b3674542658ca9fcf11e658791e887484c010000000000000064affa93e66dc7bc95e2a3a3b5f1d4a5a1e823d908c68b609d8932e437731f6301000000000000005a1726cd85f9a560e4e7f4263242db6dbcddf60ed486a9b1099d0309d4b1f42a0100000000000000305af431b09587381e8304c0c4881399969eb88f51a8f4be0d975d9872859e6501000000000000000400b51132c2eb03ef6fedb740eb193e8d760bd2873a0e0165fec0d349e44d4201000000000000009cabd5584efdf623a6e03268ce2dc4e613bfd197b8660a2556c7d31886d15f7b01000000000000002061a6d38544d536a22761c066a2aa7bec85e285b36ed8ff8d4241285cfdaf2701000000000000008c80a3ced1094039cd80b2145e9f9aede6279616acdf59042834e8d4f0f6832401000000000000004428325af01e90e77d89a83fe9ad6e15edaf61f8b330c7fbd3eb09093f71cc49010000000000000094992964a3a0e15b2605e0ffba7a8d811766f29282333b9232e4f7f87993e41c010000000000000080a27025f352254397fea53854836025560801b9b9d713deb758aeae3cb1a17a010000000000000004e4b41b8f54797a6fb26ffe5a479ebed50e0df3bc99448c05f8beb7c4dc461001000000000000007e9eff360b121321686f4b12dec16dfda4a188ba1140af11d0f0110abaaca5610100000000000000dcd3454f8d3ea698cc494f564a6410faabe06ff5e11fe297b8ab189a60a72f5a0100000000000000a0b841a82ab8a15d8576848ef0555302a84e06a11a9465e7fd4b8010650c956f010000000000000074e603d326585713f675c2293343d02c438be086a87d9241e207b0b374b13915010000000000000000d223ae247cdc0406974d73f4d43a0e5acf6ecaad8316d79e5156233fcd424d01000000000000006eaa0a5f16949f0a878aecbc36617103b7625f67930364ada6e11ac604eaa365010000000000000072d93714205b3c25a34aed59b7e4c8c45e8f1c4b63d705059c3fa6570f43fe080100000000000000aaaca9ac1af688e3e76df2b3f312a58d4c96bb959a9c20129b952e446e1af8610100000000000000488d421e225cd3dc52904daeb58dc0110c0fbbab1fb09cd7ad99cc1083b4206e01000000000000005a209f910972b3945d0dc7cccb589fee0ea07be02868bb9ab87679b8c832c21f0100000000000000108b191d066a78e842366e4ca1a208a9e3c141b739183cd2abc4041cd40568350100000000000000004380fb8aa88e68ee9795b1c9125d6a4b0695015f8271443ae0428bb3eeb37c01000000000000009c1d4e1435b05c1637cfb4acd073a1ec7d94ffff1af9348e6c00376ec8ea9931010000000000000046733c7dcd4d00fe06db6f0eca5e6582e5fde98930766b2f014c2f87ff9d637b01000000000000004045e0b0cf7ae74727d1699b05eade76ba14f63799c798520ecf4c9908cea83801000000000000009eea7dfc62040957af911aee2b1cd21c22457508886e4d35a9f716b05a85e460010000000000000094f5550fe67b1c7659682c74eb8a4ab46689c4794b11aede5a9a93ae1245ac690100000000000000223c4ad01c0c9a4cbfba126e9f584d13409b36fa835be6ce4fe447c7c1e8a024010000000000000034786b9942ef67cc62301d903a9cbfb662e4c298b67c662572c943a0a9383045010000000000000020e543e7df72b3902875244c7ee90eeed5c72b076ad6fb6911e703e73579a47f01000000000000006eb7c3078a22b62bbd07c9acca913fd1688c8a15d321838f9afd0c5f9d0c040f01000000000000009035df52811af277000a4d4a2acdef056997de429bc6d05d632bc3334c57dc2a01000000000000009833fdf5038e9a11d21b913ad3fef3c0b65375576aded9e02bdc7af37471f71b010000000000000010dc65b57fe28226b167529287ce4bc04f506ef4d799e5e99f1a3814a030147401000000000000008aca7a270e90d84cecdaaf056a5c4fd075644c3a013103a37e2a456b622263720100000000000000a43a71a1dda491d73b2f67acff11b1e0032b80b27c42ef245e1734e8a0856d270100000000000000b6ea850a97f3e6c6c29a203b9d7936cea754cea6fd0c4761923f85f562ed5a2901000000000000005665bc8e927ad36e63595056a947f3a2b56d31aa208d2fec696c0c82c1e1074c0100000000000000027eb466c8b6d1606a3d3ff5c410a314ae56272fa2087182def6c83929a9cc7e0100000000000000faaca1d3a93cafb8381349f445fb0aec5959fdd98754aa8ce9e0aab383d5816801000000000000004a644dd0a6e87a9fdba16d7170f9ea412c136c7c588868b82bf471d3ee41902c0100000000000000bc4f5a78281d4a787e4a2e04f6f56f1a4989ec0ece1c4a9a6f1269ac3615bf4d010000000000000010aeb4e23d12440e1dcd63d22cdd12ca664448a85f70ac9bd7a19632f98395490100000000000000d856cb3f6deb9bf6c991116ec3ea10a5214b1eba4c3f7c0714b5b9b025b1f10c01000000000000001036d8a47d5b1199e312962b57b8f20858f956e5488c7339393246f9a2f3070c010000000000000068ae1b9c0a62b417d7d59dac04fc341ba5876c4b721285e88f692d48ea6bab120100000000000000ca71d092a743b9620c994c91c8a52d89a2a8e9c76d5d5673b14ab0d67565c0340100000000000000c2f7c4f27f33925e3f9dc0073025d391dbd8008c37bfad33d122d594e519a25601000000000000002ea832919b7ae0258dfd5560da6745051131eee9c730a4e1d052ad92b2ed5552010000000000000038b5bc02c3598bbc18d72eb2f21416a241c90cae54beb80b23ce45243dc07e6801000000000000004ebbb16900db436886afe77a449546fe19a02cde0dfdafabf4f9455db1865d220100000000000000b287b996f0aed49360d50ebcc05eea7f3a807d273b19bc67305504199407195001000000000000008ab4aadd327b0948a30972be40e967524d08596a9ad28573fa9e64f07eeb70600100000000000000c80eff4fa1cd1cd466b3fecbffb0db70e9da8d02ce1e936240119e3d8158ee5901000000000000007622477ded0c1c9275895be406fad96a944e35aecb37b898460e0ea16916dd7a0100000000000000221842537959aecb9584a65b6c33b8666efa04d98985da826d4744d7f17ca231010000000000000068f28e4ca863e3222403b73a7bdc8d73bc245f6200efef2859e826242dc4e472010000000000000012762e9c51fb9f23df9915f45a3d4bddd8344819002034447cbd6a2913679a7a0100000000000000e4a78208b19d24631fb2bd1f6d21c32f38d2237ebe7ded8ad35377ba062f001801000000000000008c9f967dad582ee70c1e78fd69c73a35c69b6e38541d563c0c1d17b417434929010000000000000066c63b44957fd5e292354fe6fef6736090eb897e6d681033d3904109679b006c0100000000000000e4324ef0016507c32a633fe952d7c9eb5ff01389634549dc2dd34564ce12827c0100000000000000ecaa0b6415b1d148739aada5a18aa734a7b224e03dd73521a9d51aecf403e97701000000000000006aa0399566620a730ae64b6535aa462820ab1deb31b1becd8a44bebc4f0356750100000000000000d22fb431028607520394ca9ee6d00c014aa1927a3a3cdf802834ad37937af9270100000000000000a4bd4bb9d1ed2cd63f05541a107c151d029a377e6306c34b58b17d7fb3f758740100000000000000fe4f58314df60389b127bb63bf2af52e3d2752c2b8604cd95f24882e425e772e01000000000000002eb69724069a0ad99f6d06ec19a4f466cc820e5e46453e53dd24cb0722ccdc190100000000000000e4b2a49c02ec7c0a9f9abef25c843af563de160577efc2e74f6773236642911701000000000000005272a73dc370ec86b4f28ea7bc8009d8e1d3bb2deefaae42a893b50aa7479626010000000000000054b63b2423d67807830f616c08c61ad2215fd8879ac602039ee68898052ab73401000000000000004ccdb4dd89d2acb753df3bdcaa15aaeea9cda663a4dab3e63bc08f1dfc7cf2710100000000000000c267a76bb12e7c0a465046f8f44e56f830aaa11d6121d41c803e64ee4c92d12501000000000000000425bf7fd38f0f23fe67ace9760c427adb61f833273472964cf4727b3de046160100000000000000fa9cbbbbc609b8e4bea12462aa7416d4d479bd70ee288679c4e263244bc5f62b0100000000000000f0b25ea1e5eac764098804c0aa1d55782e6d400a8e70e159ca2c4a2ac94cc4140100000000000000ee020a6449c6b47c7a1826920b5549fa150160f6eadc08714e9e238f584f9c7d0100000000000000a222fdb5f2d040cc7e9a0af4111c3bc5300519af00d031db6d5089368ad6846d0100000000000000a294be49fc9ad0dacfb5b543c0caa4fa4db80d72244e834f46f871106f84435601000000000000008cecc65df5f34e2731b2d9363b79c9f9dac6d3a3f34780304b12612ddb9b3f0f0100000000000000fa35d32b3a9732459becff65e1a52ec7cca80adb8a5f8a166549a1bd2903cb6a0100000000000000d62460356abc6a6827a9ef87c2f40274ca84bbe48319e761b274d256de6c1e21010000000000000004a0aa5c0340be4a9863b3e302edf976be4efe37ce7ee3d895feca42fea81c4e010000000000000080c5363fe3830583bc115e841d40d4846f5ebdaafc874eff11d51e2587a837020100000000000000769d42736a797fa2425b47fa6c7cb6af187c77f79cb6f80431a3b60fc7be366a01000000000000005e265478d86a27d93b44ebe27f29ae438e2c250f5ff3598723fd8fde7b1deb700100000000000000bc83f7bd82c32b0a0c7fd37e880e79a383ee3d01779207b04d653188dc44ab31010000000000000082417180685125eb688e6bc9eb4740ff0b2dc5ca4f8b6ebfcd6f0d0c16699f22010000000000000062403d1b4820840de574c915f9ef4214f09609310e252e6e3c3d9d0df848954b01000000000000002c3d06c13382d56ce1011f233ebe4035d91f22ddaed3eb3f4e5830ba0b2f440901000000000000004af79c860821b341121bde9bbb57e41812e959ddf8282529a8e84fa42df3315d010000000000000074b197b2631dc08171e6ccc9a8beedbdb99f2d3723c4ec4e76e3cf5bca0a047c0100000000000000403aeb93079f45559431fb3e7259076cc498bc2c2463361278e2870eb6ba784b01000000000000006052ba40a93baf48093d5aa634bceee81e870c050d8d2009e86e9540e5b8bb3101000000000000007c7f91cd5197fd6617647ea65217514fe1cc999f42df886a250ca77d3c3d3509010000000000000006dce66a8421c42a4281fbca1aba1ba15f3b0b6846a9e4e1713fb2953dda77140100000000000000dae44eb4edeb4de9d515f7ec4883d9fbacdc60030dcc23d4488b0b8dad729707010000000000000032e7e2c789fa68a24015cc02a0b54df40c276233ea62f4f6101e597f488405140100000000000000527a01091257de47a2cebd1876bc8e6c9def4df17d5fc3f127c3d7cde6c3e1580100000000000000d8487c10cf35cd7816fd6fcb173db3d5bc2b88399a48c4ad7783545710b913070100000000000000ccfa04a072a1be9f107f87c180254a12769f79926d3b7348d08b36575c361109010000000000000086a3c085fe9dbde593247f89bb1dc0017c25a7ebc1d6371531711e02a86fad580100000000000000822075c08a6c18178479e0ee3f84d73686bccbcde0f83b46284459c5ff55a5540100000000000000ce93f1ebb11023ff3985e9545c0b493502ca86b6084a7d4971ffc477cc5ad95b01000000000000003c98d17d9f21b48629f9dc98e6ff5980a181a9d805798e0e7e13af8c2f92671e0100000000000000e24e58442f76af7830dfd983695821d43e07ac5f1df205aad3be98bdc36163120100000000000000c00011789914ce1462df3aa9dd508e2250f27fadd8380aac1285e84385be98380100000000000000befd02bd8fabf66eb21446e657dca9b453031c00cdb14f3cfd67f633fac7014501000000000000005c53dd325bce3653157bb73bd59ef85aab1f25a45db8d3ff0834a22d2c17086a0100000000000000fed5bb45125047e821ca93546f2f5577b6c2c47e09e097689efa1bfc221b3f370100000000000000964ce6b288f11f2c21382474bf82d9211df34f48d069c8d5366cbe3000bb7b39010000000000000026f2f97e6d6d1799c5fd72423bbc95aa1c2d975f7dcd666c3cbeb15fd5cfd3470100000000000000a03aead67911e98e4e566815a2724a56307d37b0fc7112391ad06eab009205470100000000000000ca5bcbc5cced0a32dd3ae3712fa758122ea0f1728c205f1c8521519968d43b4901000000000000004a1cc349c053f6a16b9fc7c091e2bf813c4dba94c39c16c8b7cdd3bc1492c96e01000000000000006ce2069f125067ee3d60eeab7e4cfda8f3774170ea7906a1d3f0a20c661cec7f0100000000000000a4c374450c0ceb1f44cd9987639530450d73fd9fe2e4d95b6a3a68f774a21d0b0100000000000000d4d07f0eb413ab26b1f6fdac21655aca89ec422d09d5e548f33e333f82db55490100000000000000228940210032af30634f06b95b273ee09b1d088c1799ccb7483942168a78a94001000000000000003e701b4795433062f42ac3bcfd991ebac66d79986193f7725b94d92a59dec06b010000000000000070f6081e77c9c6071e22c2f223e39362863c148c86645f9caba4e01e20cbcb7401000000000000007a8adcaae30dc7593ae0f5da536a93829dbb0499b790aa72e6858facc23789040100000000000000ae99324b6f66fd773631dec8f467257b3689a9d4d8330f23b109259f063f245301000000000000009a6e5545284482abeeb4ee506d4fa2ed38494ee2c4165f729fe5af1dff5bdd2d010000000000000094646b4141c7f0da5d016b1c412cbd7422d63d574a75c5062701af4a0d9d6e6a0100000000000000b2479bce76b4628d6c3d2e8021fe8e827d2e62a87d2aecd2f49ad7ffc14f0d450100000000000000c6737a15b8c31fa855d8973abbd7a2f0c1cfc8e12d4e7d9fd5afd0732f4c3634010000000000000010e2471d34dfe9baf1135c2520c43f2b9b844f75dcbf7c73308085e8efc33127010000000000000076996158b715ab47bde6a3dd55810098fd409e2459dc3937b49c9fec0e2aea1b01000000000000008cf9f28fd582a0ff7acdd68301e68b50796d27ad0d9af209498812c7c92a097d0100000000000000ee7df20469081070138b12bc0497669b3e92f659cbad1fdab8e46d9d20ca60710100000000000000acf8dd5acfb64de3b2138c20b16d2045c7dea53c840094ea1d6cd718141cfb3b01000000000000000813a4ab404eb8a241ec4992fff45f6d93e2b83441d38710c2d9ee3fa8f8c1310100000000000000180598f11178eab794fac87f4d7e40832588c1b875df2b65f5e5fcf525d11e430100000000000000900c4bf3f345c945479b669d26d379325d6ec5931a5d04946f3aac2670a0751b01000000000000009a6ddde3d25296464eb3d0cf8799cb56160f1ce336bf3ea8e50ae74960ab3a2401000000000000005654bd60052c221446c332dc3e771880fe98f3f6f40951e7dbdf6a2749362221010000000000000062b1d0097d60e720313401955fa9703d24f5bfae3074ef76a16a850b87722e5c0100000000000000e211cb107dc1f7a17e1a6066d0e638bec134a3e4da81b6856bac6bd9f2536e0f01000000000000008c630aa282e200e8cc15602fc0bc84bf63a75a4f8aa2858ad189dad0fb2b191501000000000000007c1289317722b111df6eca52cca0eefa8f3f84714407b5144e7c9410d7dbe94e01000000000000001acae67a3c4f6039c7587052b10dd73b99dc98efdc4dc48d5bef642ff797620d010000000000000046ad7c1c9808df5a49e2235846ff0ca389de8ef53d4c0dddba3b3ce87f5bbf2d0100000000000000ec68b260e5096b31679d8f038a6810f2506f00194ea4a2cec5133619d170681c0100000000000000e0abbc0cebea4c81fe2b9bd6f7a26ad35378c3ecd159d70c4e096f8bdf4dd96501000000000000005e3199c563a579394a3c8f92d6775dd4cef5cdb62e1614a4f7332da4911240080100000000000000f29dc1e75456c1ca087f6b57ebc1125b8c81b8a927bd343b8f17d625c7be851f0100000000000000688cb49d1a12586b32e9e68db41854d586cf88c05f7044b5dbd820d95fcc291d01000000000000004a186dd10ef461f7bee237f5844e11018cd988c6ea3463b3d90675f9879a491e01000000000000000ceb768bf920b8649e474498de67b7aa6a7bf1c092bbe09024e264a26995984101000000000000008647ee8d29112156fe4b2d36228c820a9106bda097c397cff06854bf4fea3c7c010000000000000032b6184e2846ac7ca46496154577b73c19442bdb8082c8e7d3952cda7ca1964a0100000000000000207e1288898682452ca8ec2f0b8965e4b1dc102f7e350d38c23a4ff1bc2fb2680100000000000000009a8465ac9f47c607f64ef7d0a7ac77338667e52df1b514cb2925962c11a72b0100000000000000fe1097b19eea68bd41c19b2272f30738b78bef7f4f48f749a67ecc07dde7f1650100000000000000fa5519c73e54a8bd937e0840e968b1bacf5356e665c35f2a1f672df50d8e706d0100000000000000f05426abe7ebadf00509c9957b2a21abe6a5526541a33ca0435a3aff6cdecb4401000000000000001a2d2ae0a251e8886396fd88178590c9d2bd0fadf99f6b3aab5e98e92243587b0100000000000000245161b761bd524ca4a238b683d550eda87e0282ad18b9378bf26c932314074d010000000000000058189ff63dd1d5e100291df6e58641bf221fd68864411673126fd462d96f0c11010000000000000010a8ebe9b0f3ef2211c6bd6f8ab26d65d2300bf05e141bbfb432befb6929e73b0100000000000000e47ba9d5586bf43343c799cc5ee4425409b096bf61ca938eb53ed901afcdf151010000000000000062d899fa2dd47815b54e539f106cf26841312457e8fbfac992b0f93281bd62280100000000000000ce34ffa4a44cda16256212f3ec98bc9d5fbdd1cd98fc8ab3efba9d522c020a5c0100000000000000c8fc2ec27039998a22ae9efdf508679842da1e2fdf5b03094ad125d5e2555e74010000000000000068e83bc553c4171edfdf0b46cdb6c8eb66866289811a575915a490b01c82346f01000000000000007e3a520a8998873806083bb51c6898b65ff0855d918780adf722ffd8415cc9570100000000000000447e4a3463aff0a49728e28c145b112e1274b6d4d1252e1dddd3e24c1ae1795301000000000000003229a60471a685882d5cc3b89c4584e60485765b5aa7bfd945e46cff83de0039010000000000000024ac580f01f8ace4547930f2372d2991d7651c05a77f20a82112c31c2690a4090100000000000000f8f41ea2f47473bc736160a0352d3de195cd7d64733d366f0537ecb8a154a6360100000000000000fe1767d98091db8882986485e32fa7c40211e090d6e1789046716d9fdccd8206010000000000000040c57cad1147eaa05b0bb552e89e74ff94edc3e4fe30b646a234d60b2994125f0100000000000000ea117e561a544319884da2e71a5ecd53531938d88c45f6d2d8b2457682bbfd1b0100000000000000b80281c05dd71e1519e994eb1e0624b81957769a7043fce590609773d0f2362601000000000000002454ea37a36c8de46ef04d3fb125a2c76ef56b0346f0f898e1afa653dc9297560100000000000000347052dc2fc30c4547017435ac9195eb38268f1099f916933146d2cb89b7a21c010000000000000052b6ea71d40226ef96ce79b8838651614a0fe8b212581a41c75023844a144b230100000000000000904745952c1eab87a6ab73c7d72a639499502d38e5e1d2585cefd305a8fa4c6f0100000000000000dee6543f7b7130fb6902473f561353f5b87d1782a277f8ab575f463f5778ec1f0100000000000000fa69f9bc1d3599775e956aac7100495f01513c1ecdc69c6ac8efaf4c483e860c010000000000000038263ee77548b452714409b36a249f88fc7c65d70d7cc8054b8ac23c8d6d8c49010000000000000090a34bfdf121a217455ea8b28b129b6810fe3a1f51362709e87735b074de9c730100000000000000a241e282c8464bfb7bd604122cc61b522c5831e6c8029375ecdc8d302dcbe95a0100000000000000b4b2bf9ed76f85232553ce4637f8877d96b373ff193f8067030e5d04c21412120100000000000000a20972a3f9f17b3a8bfa289153fa2229e2e0db832f026fee9531a9eed8dec82f01000000000000008024d776ba0f6841949f1282c285091b9069258df986479b89b8b4e29fa9e83c0100000000000000747231253938dc1c2eebfea199ff351837a60ca99487e8de5f794ba516759c1301000000000000005607d099e625b357c2b9f780aa87e5755cd39d2092516679ad2df8eaf79a4557010000000000000026c33c91fc7b65e80d888be26179beea1bc52fc4425c555df719a5974a33e4000100000000000000e0eac0947d0d3cbb26f840f9ed46e55a39dc42b47c0836b4c884db0d9baf1d21010000000000000086f485d4d14984f7fec67efaae33a8f8330be028b2a5d0d90b061cf4fa1b3020010000000000000014499f2b6d56b34a735e6cff44f24727acd246473b5e69045069c692cbafda6101000000000000000cb429c00451cabda4461a68d1d054ec397d19cb57111b8af58e7b5b90bb1e0b01000000000000005a94620bd96de12f406f81ead002e302a59ed96b0b779be22def811a1e8b011f0100000000000000dce101e08a1059f8799e5d5a766cd7ec3d9bae0b1d4813ef98e8e93f46ecac610100000000000000207bdecdfe43e67796eb72047886fb668319d94fd05c41c5ac968263e55683560100000000000000e22aee806088a60f8f113dc9722900718576d88297b026fdfccb05dedd57b0540100000000000000a8eaa69cc6c7b495fc98b3bcf7ecedac250a30a426864c47ffdbaa54a77e132701000000000000001e50b0cee0a40556c1c21413815c8c077103039e31586579a149b694ad3018750100000000000000bc34326c16811207c825a5bff0111b321f8e68911eda67187d4c3d704fcca52501000000000000003a319da516142f46e8f6b17ba9299d81f24a8a26db53734247ef4a25da8e23510100000000000000ba2a93866a7a48eb754402eefce96c5a03019b1271c130ca7cc413f74d45521e01000000000000004889e344331353012edc31bccbf3535717654469ddc8a9c558e718ea27858b7c0100000000000000c417aef827c1c0335fefa6876c2c64464fc604c7dd2617503fb30e539605797e01000000000000008a013adaf50ad92a08e1e3efe62658c755b2c66918d35cd960d8cd584a8e0c3d01000000000000005a8912adf5015bd18de18819f2eb9f7005b905860ea4ffb680a8b92e30de3f0c01000000000000001c21264727f0873d34b9732687fc1d876935b3773d6a8b39713b286e682de21301000000000000009ec4913462fabd60a8dadac55e082314b4b97e1566c3187e19de9286395ce308010000000000000084700cd219320c636a8fb287292709c5f268b44e8ac47973cf8375f550baea7a0100000000000000506dd834df805bc18b721ef11285f14e401bc5abd5698109991133bf2807a0580100000000000000c83eb4d728980557eedbaa0f21efd8edc7a852192ff3ac7cb48cb50564f3b67501000000000000005026ecba2b42e87b673a51686f1e7b4e7a6508cb2fc3fa883db184b8d5736a020100000000000000ce8b91ecd1df63c4e4c5bd8b59c07ca4a478c70acc47f8e7be984dfcff7867270100000000000000d6267c181414f98a2b2920cd5fd3ae4a76f8b1caa3a1b5db051ce0e448af716b0100000000000000a69f0b542cc77c0cc1db089b0543f7e9f6bcbf97a88b4f59db6758ad7f2a116f01000000000000003a505d573d3ba37c34014e885db0f0c6e57bd0ac01941f7d91e35d9db15dd93c010000000000000098fb560be4db49b304599a13b51bb18641832d0728a0406145fd374f579cda0a010000000000000022f00e70335533575a249463304694f0ae3b5552764a3cb8e08a7189f9c3fe6b01000000000000003c268e4423ca53f3d4811048c94b8f4a32b17f23046c7c46d668001690865b3e01000000000000009849f6acc7189b6582350d3007b9a85e835342219481dca15a97c91558511349010000000000000028e15963314df110bffa94595b184b655295ae8bf4839b6f5e8877fe0bb22d4f010000000000000048d5297c8d8b117371d2b2ffb5842428716bca3723e31fb5a279987ec3c8077a0100000000000000da84bfe6419a9f4b0cb0d3c8c2b733478bf1fb466ce8155168820ab40663fb3801000000000000007ef3574b131ee21507ff0af429c12474854020f2409bf60f43ae059e92e83d7c0100000000000000e62445a43b4dffc5a485ab5088b2fbe5ba157030e2011b865fa9535f2e2a5a1801000000000000003eeab6d21c395d432ae4c00e4bc4efb335ef03a3eaa1cc491fa48f2f5989ff75010000000000000050c946f0c639550a49abdf37cb32a278007c053f4ecb5f3ec217b3734e89496201000000000000009c4d451cce10608e1a7e94f7ff08fb60917e087ba52b71f72dde564f3802ea7901000000000000004a20e7bde74cf487a1bfeb8b1a82c0208bb44e2491283371c661aa52236bd31e0100000000000000a628e05fbb6b2da3dd535e921ad962bd60309f5fbcce6fa8b2afd5e6c3e900290100000000000000b26728aaf3e0fa669444792216f7a22cd111eedcb00d4dcd89600ec13c25c1300100000000000000b0a6c68327516a6ee821eac25712e65389c31107ffc5909f808b97a889e7e22e01000000000000001204e5e727047d557dadad1e2eb5c313da6d40bd425dae62721c5f6dbaccf92a010000000000000016c89b7d7d083c6e296a13e9b9992254754aab0abbe738ef2b6e906fcc56d2770100000000000000546988c61188a65c68fb1921aa4ad361b7b066c919098794e4ec63a9b273a8250100000000000000f694347343186a3a31b77eb380b321ca24899533e308d6db538ff99489f6cc260100000000000000b8c2c2650a123ff6e1f3f9a4852e1f1478d29b82208660d288711453f59975100100000000000000b4e3522966655aea64c785d5aa0d6832131d37083fd7691bcbda2801daa8465501000000000000002e3e3e4de086222364855c85beafd2beead75418690dca00cd8e563bdbd0307001000000000000003a17d89f5ca3f4aef567cfae6f52b9f306a51af0afd7b88754fbc0eaacc54d3d01000000000000000209114c257630424527364790ffd9cb8d0959c00549d89596504866fc52953f010000000000000098ccf22f6798e7d8ec84d5860fd78a7b0d99b70d1466c38e62fb8dc64762624c01000000000000006e432f5cc81bd8aa43d024e530805df3f15e6b3c6ffcd6ddb8ae3ed8f8871d4c0100000000000000805adeb5926bf2c65b199692dba8930fc045d4847c9b45d5517b419fe733655c01000000000000002eb044a7cc9edcaaeef47436fe0670383de1d43b7a5733bd201b4093156fc079010000000000000082d79fd6df139cf21b0b46f4069f824d646b050cd9bf5180c15514b1ece0e65401000000000000004476a1c9122eca6b9525e25a2a1b4f779786b6f2ea8c75911a19bdedd4ec08160100000000000000f2ac443b61cfe0350c050f503c63952e39d7ec7f10ce1b919a9e3bcdeb993a3101000000000000003c251fee76b23c34c9a5f06119336090aae9cc469cc4792bdcc4fc569e47740f01000000000000006c025a5a5eddc5ff6d1979c288989696e81805924bf1ba1c800dae8756db2e6e0100000000000000722d9a8a39b1e5766f87106a5fe837193b0b970ab71c05615a9e24d8567e9a6f0100000000000000a6ecdcc57666d43503c12b924afdfc7b90c30c20559b85908e85ea8d97d112520100000000000000b26ee8cef3d614179446006b926657f4c482392ddce0361e31640df2bace206a0100000000000000f8511ca8f3cecf0e65c73e296b8857a2dde7292980a18cb6c95982f14caf6a70010000000000000010b8c40283b0f545f682e538147a2814ee763833912c42228c3f4512205ba719010000000000000006c43fc03932e3a376a5f7a0b21bbeea239d1e4861c1c505b4876f1af187b838010000000000000036946d16ba1ba5e89b56a6d13053a7f8582513bed9eb904048266709cd66b57901000000000000001a7cd7c9e38baa21356433cad25e387020bc113fd8b325ad620febe352f2546601000000000000004c382d418e7deb838aa5524aed7c069f0d9f17c279a75b119bf039d97be0c8760100000000000000e45c57ef2b0b7acf65a8cbbf007b4955916014595caf38c7144257283a5b7159010000000000000038369575154ec55cfa61b3f6ed1fb8e95e1f75dc8c5853013e22ce6857334d7601000000000000006aacc44496f2919e0e2bcc0ffea5d2e0e2c8c4147cff8376c077d8f8220e87190100000000000000e62d2fe70d02977008160b4c3a1dc6ed45a4c872824b87e57f81c30002b98b3e010000000000000018fb6d5821907312f8d5dbdd003a43d969759d33677b97d578812ee72571fc3b0100000000000000c8237c8af9420a7f1cd9d5d0a6ac0786a675b1e7c54be4fc14b2c47f26bbb71501000000000000003e54803e6cd54054749e7415bfc95a92c22210c6d57d3969488e27021bf2f26b0100000000000000764c5346ee442fac7c86ede40cf8a1b9899b876c7af54871de01e0da34e39611010000000000000058ad4bcc02ae69966fc6b9c079298e33f528ac5ed6d5e00bc0707a2c34dcc64b010000000000000074075ef0be7201f3d2f61851e13852cbcf3429c8e39b9fd7e68929750fb088680100000000000000a0f44359a9ba95621aa50df5e954a1bdb4135ceb27ae0bd1403970cf4c513e0e01000000000000007a6d3469e8fe48a49c88755cc27e32d15d0357fd550c3e9ae26e2fb179c64a260100000000000000f81147fb928508d01695cdfa9efa83d50021fe61f414c67f1fe52da77e17b50901000000000000008e77abf341c275566bae3ed78e6bd09533d808a6477e79a713d2a5ae1f10e1280100000000000000a0530121b628e228f54d9627b8575f109c8aa9cd11d352c62451cfa4a72f79330100000000000000562b08919cb7fbcae564e4a6184c04aa7e4828a5a842e1f482344ce2a66c816301000000000000000e9addb6311bb2332e1ebca84869950fd3467ce104996711d5d15533dca580710100000000000000c4734efcc224a130e0a88ce646d0b12617d8eba74aa63d6b15d464bbc92ba4430100000000000000f0ec4f5deec15d645ca0af607ea94cf3bfa804aebc5189671037c7aaa75d397f0100000000000000ac8764044001f80971a06a1cbfcf8e2069db99320dac152825325c2e02e02e2d01000000000000004eaf8faec194419b7352592202ed99fdbf4d1e3d53675b66afd6857cd987430801000000000000006e4296c5c30cdd8c878fe0827aa001e2543d1ac540f5f71a720aae085544b8590100000000000000ae96c86c05839819c2e9fcf7538cbc514dff32db24c50347fdbe9e40b5fa1d16010000000000000094265215c248c1c32955067977939c75ca1c68bdb71cafbfc400c49fa39fd131010000000000000070b89893ed5a3d52dff5fa29dcd49027ecdca324d82b603fd90095f5bf98c153010000000000000030436e184da570ee7fadfb3cbe45ebdfbc615662c3cfbc00c9f6b8280a7ce90e0100000000000000c0598669aa0feac24a5b274991468bd00357306894b1dcb6d5f404c5abe9d63901000000000000002274d66d8a218adf30e993dcf05369a9953147c1cff1ac4f97d1e3b165069e550100000000000000a6f8c679f2f31d5aab1edbd1eb93984198273a45c2022220263c066f4d7e432f01000000000000008aba440681aad15ed7c993cb634e9c0fba18d6b51203e11b126ad5dfaea10431010000000000000094dbed8509f53288f66b6f98de1d405728636f653fa797d693738a53eebf311c010000000000000060428f6d6eb771161273b530827ec6a9257e80990fdd17414c494a6fcd20f40901000000000000003294271f20f5dd38600c7a28817f08c71db6c43cbfadeaf0a1d3d8a811d3eb33010000000000000086d104f9aee7ca4745b67c4dde99aeef2bb1b71b306ced5d2a860683492c834d0100000000000000802fd4488ded389f596b06a6740843840e614530653928140fc279e518f71e5b01000000000000001e4af2935a732692530925ad858c08446fb4ecea1003dc9f28c79806027d93720100000000000000ca7f52b42995ffef32dc5e1a463c5de00880b198620dd586afe54e09bf8b4f6b0100000000000000c458a424c7240a6adf9efdc05626fde2e0073404b9373e55e8c880b7fc35bc5201000000000000006a02168c87adc846f0bf7271011eaceb8e12f1830178dff60b22fc6ee130bf3801000000000000009c95a09363064aa3b3339449ddf42f764b85360eef65fcc0c6815463e9f0da760100000000000000da81a90004e1afcbc9d6e42605ed3d6cb101f3a97842f7e95102c600e35606150100000000000000624d200da8e14fd3e016d73b28dd1ed57edb02204614ac5583677f4e2fef1601010000000000000030bc2e62a69c39528cd1e8a22702913489e1fbbc0220b884e1f30dc8176b687601000000000000000803709b1112bcd4d1049b2a4e171894a247d5e7b0969cd2e8d596d00c32fd2f01000000000000001a2892e76170991d57ccd0a0b40e6bd1e73b80d131b70330f53db742c87da3720100000000000000e6d8b0713c219a46666c3558f5075fd3d4552ace340c87838022c4ff52e3137b0100000000000000ced6d9e72176718ba8503f3606ce9324a1038eb8432ddcf3ee134c208c1a4c0b01000000000000001ad7e7191b94ef20e8dd01fd626c08118c134297f4eb05ca6e58094571418270010000000000000094dc1dabe13768f52452ddccf1c1619ac60775fdbe4f3af85210de7b10f20f5a0100000000000000aa59c3733e8ccc7b652efb9d3455b8b002484ebe92770486fd14a7f5c671493f01000000000000002a2208765a103fdc4e010943c164a22d7585d7bad2f94120643e4fa07b977e1b010000000000000044f1a3e913bbe55a464a31abb509a16b269c25947788ffa44dbb4318c16c421a010000000000000082ee08e1738c194fdfb94e8de6795bc68fd2f1501436e75ed1cfa0bd080b6e740100000000000000b86a2ecefb539728434812500b915035beeb9399b59ae9092c7ff568ee93937d01000000000000004ea271b18bf2d162a3d090065af32a39b155a4ca71ee525c79b63dfe043c7f660100000000000000da8baad43d414ddba7af5dcd87b8585734ed4d033da44360c1a1f93f4217ba7101000000000000007829e8e5f8fe0999bdc33140b337a9b3568cad82c55e9910156a0d80feab3f470100000000000000783f71679ae23ddde049dd27725c8d701488738f540f0cf2e489552d73c720630100000000000000346f054c3285a2055e3eb211e8ddd43bb8e56f2bfc2589a81a9402779f311c5f010000000000000064b4b8fea5786b672708d6531e7fb50a8f9dbebbfb2dda4a5eb0f9f4e8af14320100000000000000fcd483b0b3b5584ed43955ae8d67527c150ec6716cecf7fdb7f06280e2501f360100000000000000c0dcb267bb44e2d692010692ecb44a251b2a2f5d4fc464fee86f7eee90db204b0100000000000000ee01c26d2e5e3f9524a0e9337f7caa084598031d3b9788de1862fb7cb335ca2701000000000000006ada9788f7eabb40d9fdd20d9288debc30017d004f4c2af3572f0fadd6cfc677010000000000000082967807c96af3d8ba0d60a0459f160d9af72629359f5de85512b6ca6506817101000000000000005e9367aefa57cd8548568ffb69490ffeafa1aaf53b8a5764bee5937f6c7eb10b0100000000000000f8316359f41db3a972e01f930ae44650410a4d81d7231bbe8423162eed38d22501000000000000000661630e26696b8a4308dec3fa4b21e458cd207d8f7fe24ceaa9aa24442f52210100000000000000f6b9e1f24b16ea977e09f9eef010a7e480e9756bc75839fa64b020345ee331110100000000000000ee50f7a323e52cf99b8e835cd02f0e9bf87308d8c55ec567d74fece82551935101000000000000008cca9520319ef1cf46f1f91f59f2562e63d32ab8d45610500a4b71c77f31120a010000000000000008530e1900366759ece68ee4d93970f7eef673cc02e1434bdee81b34d6df570a01000000000000001a277517f053881b6899bdaceb07531b0ea921cf0451902c8ae6100c7d71683e0100000000000000d25948094b390698633eefd07c39fa18263fabfb711e1a01632261e46a06817a0100000000000000f6f3dd10489598094cdca63b1d8b54ad279d4bdafdbd5e4cdc5cdb298423f8560100000000000000dc72b6b898dd9441f88616bab41b159a603c0fe8f4cffe1f1e10a8cd9070bb1501000000000000003625d372ba3b670fc6ba0e6587a7773d308211006a0c9b5c64171cb4529a22250100000000000000c44e41271bc5bfbe3b87a18aa56cab38114093dd6dd72b433730a5f41e1bed7801000000000000003800b5d99be3fac75057358f19828154f8604feb684c2ef1de1f15583822030f01000000000000001a67feabb299ba743551fdc82b10087f7c83c51ed8af344100c902d19c86ad5c0100000000000000a8acc2ae1dc6aa10012ef1ae9f1022fd809661ca63a3fa672f52c3c49aac543101000000000000005a58cb782c95abadaa305073c0c0ca11bee82b3bcf710e2629d2da1e5dbfb3340100000000000000385f1e0ae728a63ee8216a1eae5a28eebf841793deb4200c4da621368ece93220100000000000000ea7f0a7f927ccd2e9da8d22659f160111a89e044e4c18f2b5a4a233c552d06420100000000000000d41ffedc8b57a7148f705be9d1b598894c6b1b9a648a1104fc3f20dffc220b760100000000000000fca60a110d4846057f42255dc324a7133f3a44a548d4cef5a858e7792c40275b0100000000000000f4740708400892344f0f3c898b73815f93724c669015458d3dec26d277cce52e01000000000000003a1cd386323582ba078e4a4db47abec1c81c118e79c1bdeb228cea7600e6c47b0100000000000000bac5e15c0a13cd1efe22588efad040a84fa2702a18648582875b0951b6efdd030100000000000000165f930ee8a88138ea7b66de084d2ad75ddc5b47f8bd2c649c6180d0798f05780100000000000000106601ea825257b511ba9e9914fcb114e10aa4702e88de544d52a2664df04e220100000000000000c2358a31820bcc5137a556eb2f56d412f816a553cda733e3a71599821e790a42010000000000000030b3e65d400e10038a5ad14b1daa6755a483dccca31d0617ab9b298b75a7e52501000000000000007e24a8d2cfef8ea11b132601c4ff928f0abc99a8b1c3cddfa8efdc978a876b190100000000000000aae0f064dc19fddebe28ad3a980174907ef113b6b409f1849e26d431701d6d4d0100000000000000760636dfce5a4ba92c5e074796c631a2ac9c8f7ba1306e1fdd49a89660ae970901000000000000004418debb207ba143b02ec7f8ea50858b092d99d0665bb00fbe20ce62230d91360100000000000000a6f988c5cb6c79e21e473fa7650898ef5d41182a0fe155154ba7fa8518e510470100000000000000b0e489fc3fe9f950626fcbb193ea260bae624d22575a42378cfca74021f32f100100000000000000f663cfcbc6f9b86da26b1e90af3488b028c7ba2d137486f83839f4403ebcc91701000000000000004ef4d62870f301302e0bd5b6902336052c3dc0e93fbbb4aa3e2f4434d4f882760100000000000000ac7b9ad052da49f2a7c642041b0474a57de146b83be7234a646397d9a81be029010000000000000056e00b09248e5bf0bb4cfbb69cd6df98c34b31732c707c0c4b11b936d6a54a5e010000000000000022354c2c6bc0f1fccf03d4155c0812c823f22553a97f26717cb3e0e2b3943e7e010000000000000080602b328253f7f7f8c0fa4a33360bf03a5985d25eef59e7f764a7b72a114f340100000000000000ae8776545a5f2f1563abbb3f8b83e5355d13b407723da0ca4471fcab9e737c14010000000000000018d709277e83e313b0918437cd475b5b7e0b787cf95f22210ed6f49cd79df16d01000000000000003a4fa513215c942db633fe1313f23af5dc50057dd9f80aaaab3cb39802ee915a0100000000000000a6ea38f43040ffb4f845d75dc0d6ecee7778a72ea6d7ec5e7bc3739ede0a4912010000000000000032718ddc0d1af06a3615660d5a3a2c1d77c0e6830116e6a16c839d9ed49a4739010000000000000056d3b96256a58d44fca543386743ea0ef467a08a58c395b35e059aeb82d33e3a010000000000000016e4e7a211f83ddf8faa3fb1e2e780ed2538a2c18d7aa652d228530e41f484390100000000000000d6d09f1a5792006793e8e4cc9916b4c2704dfc467b8adb31f9bfc6c8cc86625301000000000000000a16f7b9b863ee3ef006bc9a7d64f7d8a3bc3602012fef3e7fe34720964d9a3b0100000000000000f4f8bf17fff73a8b261081a6839e3f7c13d0e26d3b9816dfdfc1cfddb0d7164201000000000000009aaae829e9ab1e7e3d3aee8c339dd9a8a28c4ee7ec7673e232a545d992996a5201000000000000008c64163d6b570fa07301436abc38c078f93bbfb1599a606a63727448aac840080100000000000000acaa3b23fc41d9b7e02557c7a7ab31a0749920e87677e2ea80727b495e003f580100000000000000788a3622f6b28e0b9cf17262ce72fc02cba07668e7665678f43533a8fccd974b01000000000000000801300f325d71017575e99289816ba9700c3cce400e7f4a0a062c8db5dd11730100000000000000fa516b92a610d49363495a5efac22768972d05bb3601d874725ea074c3b38b2b01000000000000001a0d89c6ceb4e5ead836db5712c2ef8f48b312e7d4baf40e9c5ec3973c9bbd5901000000000000006c0fea2e3f2b69e67326633cbc211bc7b5ce08913feff87cc69b4cec76894d4d01000000000000000c53ab2e5c9b4d41aa4de18cee7df915e16a0ac41b02471cd7a709f606ff994901000000000000003ce64fa2a54a88a88cbbe90dd16439dd3fdb0b94d55e6fab93e2114915c8ac490100000000000000ec8b65b7fb9cac2058122119ebc80575a0499fa90603d0398706992bac9cb97c010000000000000042fe59d6f6b91bc3146e7ad526cfedd25c1eec718e620105ae203f223d115a5a01000000000000001823c300e44916c214484c40e571f5825b41ea9a3a6dd5eb469cb63deef1c43a01000000000000006ef25067ff61d7adcb34f4d056eb42d39019e7b223a4331b471f297dae3b58260100000000000000aa96f51d324ec85748307f09101b036386021d7f54cb8ba510e969016a684b030100000000000000fe3e4a53df7781cbb92ea2b3b57014de56eeaeaf2a1cb301d48db1bc768f3d450100000000000000cee709118a09af45357559cb5ddd5ea9c4dc3d9ced45d65a8dcb836cdd5b6b170100000000000000e8c7bcf1afe68b3c0392818f83037e67c7eaa3df9f5d5186d26816419860887f01000000000000009882936fab346edd6a9f4e9e0f43ba66d23776d60fc7d5b02f8eb2646be56c48010000000000000008b6a79655cf12164afca63cebf96a6de9a8cdf9bf07d6114037bafd7442d15f0100000000000000d4ba28989bbc1eed11dce36c6fcf9dc7e8a30029dd4e9cb49e37a1fc025ba32c0100000000000000b2cc463bf2ceb0e81e85efcd4366a70b1a07ccdf5e4cc590e3bd1f81a90bac2401000000000000005ebd6202c8920742b7ea18c7b4c972a4d9f932f5c798dc6caf3848d98b17f52f010000000000000074b69497f960330abbc8baa6880fe6208d81d51a6a9e8502d763c5eb0588e36101000000000000007afea6044451b2a89a93852718241e79edabda900647b519415714a3c2f1241101000000000000001a50d08eb5c843075e92aadde4d9fb9fd82b498d986ce6644d7c608abcdd08730100000000000000e8933b62d7fd087b53a163bd58915eea0ad77415b5abe928009b655c1e5c73550100000000000000781510e738997cbe15c52e6f71c73e01d7d976053def218c5b60068a7b32ef130100000000000000787f5599a47970ce8c9696f6b81ec2757eb3a076b3aff063862565ea3b063f1901000000000000009c89556174b54cad4b10d61bb79341032ee1b5082a4d518dd3ed35607084a66301000000000000006ab42e0eb56eb22cf20023fdca6ff97344b9cb108553362fb1e4267c4c901c0a01000000000000009866f6e20ae6bdea65afb4a90e6e23d4ebbebafbfab5cf9becdabcb5a608c94101000000000000009497a12c4fd9e24ca7a91abb5e1b43537973c99d7d0f1989a148948b9af7330c0100000000000000368d91d03c3649e39ddb803c3b74d8e8a7949b378a5de26c11647998dd8c377d0100000000000000fccfd929e850d89729955020826bd2281573d730b58177c098200a0eb8618776010000000000000032e4b5ca71ac1972a0f5f3e690b9555f183e6683e6901e9b868c51ebee643e7b010000000000000094cad4c929e213aa077e0dd12d261e5262fdb9b4038efa5e20e122e31e837e6e0100000000000000708226db190ec9152e02b3df6ded22b55d7561fe664a98159a228a96ba31c106010000000000000014223acf876f0113d636af4321753ccedfd59e7f10ac90211c673f4716defd5201000000000000005864ca82ae54b225c1844d450c93e92016fd013e8f37164572775259b2fa9b3901000000000000004a9e04759f8b97cf28b4a6fde05a365f5d8d72a48a3619de99ee94f2c440832501000000000000003c93a25d88274a519c8c234b9110f9c06bda3a7ad587f3936166835ed6a59b7401000000000000003265a1cb3b8207af1d088c193638046abbb911d5d4b31798b87314501d8ddc3901000000000000008e4c4d3eade13f13a09906c7c5eac038e80de28d9e06256bd4e24c8109e79e570100000000000000508bc075773c4d07c73f6d97cd23c7db512d4ff79443b7620d900f05759e71760100000000000000ecd5007d932f952fa6a31cd705be9d924e8d8da8f9ed984a4d00c027b2ccd802010000000000000064d322f5132b5ef8d629f51eab5d61a2fabcb6f8eee3d3cbcaca78339738fe090100000000000000e8ef3e5ab1db29a5f04d79f770406bc34340756b2be2ffcaacec219d4a370562010000000000000080613bc7a9e0bea05804071a5f26b33bdc65d4ef7220e35efe097ee82c6a4f47010000000000000098b255a5baef61f59d4d5cf3dc8aeb54d50fb9c66a3b90058ec14a7e3f4b3613010000000000000074cb201307d10eff0349f951a51d2eeec91c65ab0c641826c6c3c558cc510f5601000000000000007c577db1badfa9cc7900c45eed742fc0cc62bd13307ec2a364d768ac6d58c91401000000000000001e322373d65d7935be40708e13c0832a8a040922bf20ebe96a568d7bf75f5d0801000000000000004a90501578b072a68d80e4cb78c657ede9d72f2318f87ab22d93ca43e95382420100000000000000d6f370b579b1b3cf6a0330568b70a5a602c05269ea00f87fa9b7ede2c210a67f0100000000000000de71b10f6c8c6735256a4f15dc1e3b7510c4540e4f16e0c9ab0c91f6c7a1387201000000000000009ebea3e7d902e6560e162243912aae7c31f683b66bc7f36ba6a01abc4afb893801000000000000000e4b555beeea854d0c90cbebf7109d9e84b3be709fd6cdb07c2f04cb9aa5d6700100000000000000c6e9d7841ca38e8133d5ef623ff586162280510220d82c94835225769755a01b0100000000000000461dc32d53a4cf3a2a9552fc0b5148f1d8978e7e592d0015f45e855eca698b00010000000000000006a1361fd9dd1840b26cdd1188a4f7604c6fdc0f7cd557b0702bfbadbb28fc7701000000000000007a55d4f4e68806ffaee585edf6f92747a647412573149b8587e1855965c057500100000000000000a2fe139ae1e5b8f32e82b458fc5e924fff3628a51b55826de17d3b215c219c5401000000000000003c56fc11706317f353c421efc3df4287ed81f05041a30d14235dbbbf8aaa517a01000000000000008e6cc150514be18847872a807b05aaac205b702bc3c4678258a743e50e9e2e5a01000000000000004c0fd7e87ac9eb4226e16063e87227d48843657d723d9ba032852d76c0ff223b010000000000000034b6f378dcc9103d686fa7f448197248b64fc52defa62fb82e1a2fabaeee7c2f0100000000000000404b2b975cad782c8cbcfa5b55ea5592f59d0bbcb478c7771533203a8ea391600100000000000000248ea557096c7b94c81ecb56b808e3e1a04b30e16d15e11da9fc4f50f2c0153401000000000000006641b49d20b94e97d66fe673351f9b61becbe531d24a4b70e17ee00bb810b72c0100000000000000aa293b11cfb0a82a182485879eee176401f9bd3fe5fe9c09bbbac43b9404d16f0100000000000000942353f166b2857b3305de71753f1ae599420936806600b9335d69e1b628382b0100000000000000947d3b8ea2cd77dae252b31f095b02157f9047e2a1a3e861bbfc7b3dd50b293e010000000000000044b3fd8952decd79ba651540aed838ba6164ae94e32de36b7e30f39cd8b2c3760100000000000000c85f44eab5b574408ed3c32be62de13ac84bbdaa33ccbbb9704a5645ca477f7e0100000000000000f87a1fc124ba62746196b31952bea35b3e4a7b1ae35cbeccf2ff92d4454e0b27010000000000000046cfd49facfd18c680c936d4c3ff5cee00b7fb159744acd5dea2fab7b996362301000000000000003a7e62ec41158e5b20584114db391c1b2afd64ca0a14ee2c357d220e03d95948010000000000000064ddfcef7c0c59a2446fecd781d3d5aae7c39bafb26dbab9bd48d969e4ce1f200100000000000000d0b1ae8ab9db76176462cfc9aa836e042b7f624a48304901abbb1ec5e6e46a7c010000000000000080eee4729b02a85777700e749801cf83c304584618a6fbd77ed443c3b8a2270e0100000000000000c633ae1650f7a1d9c6c107753cd2ce12bc10323affb5a675e17b39306db6ad790100000000000000a2e743e4ba1a3bb3f97a8fb5f1fd096660be0ada88473aeb2a45c769560cfe5c010000000000000074becc349486815ed5b71fb26bf0e48bc9231a3fe18cc2b521b45c2f4cb4c1430100000000000000c82054634855b9a8441bbbd9dff11776b5efccc2daca80f4d14178e6befeee660100000000000000944dcf3e822c28fac0f575087d4861048fbd3168321841f70a6f9af7878a8578010000000000000096358090b53f3b2a3a588c4bf5a8682b07bc58bcc335182063b994ac5819931d0100000000000000461e9bd3103a40edfb3bfd94b1d71b068ed766b6716023000a3d1aa5a9d6a16f0100000000000000c042295f93a5d2a6782b51cac4f79aa2fcb4849819ef8654da6448e0c30b376d0100000000000000a4984a528345139ee5ec8dd4970bf7beba2da536ca3ea09df3c9c7752cc3042b0100000000000000ba1cc41413e67d5831ee75eb91f507e4e242415cef92d10c8574756d38f05f2c0100000000000000fe5a53e79b0586e4c7a7e814af860f13dfabf3c54bd0ca9ce81042f8c4675b27010000000000000068ce69624707bed6f2072030b6cf743e7579ac296205d73ba0bf9a520782874f010000000000000084854d183a5948a7962f13bb6ded8efe5e041a970cb1536a206b9c8f2ea5842b0100000000000000f619de47cda0c3177ff0a5d13f1e46f629440d31c7a7716fa775028f97c4a2390100000000000000248e92c8f85723d777da5e140968fad29943c76a536834164ed4d1ff93421063010000000000000058666c4227a948af0f848127843efbd9def367037a0ef11620318d989f0882370100000000000000c836b1fcb7ab453aa955d697fffe154a6c69cc5bdc3799e3a254dbadb711a1420100000000000000c214f7deded27fe33a91fc1aa2d2c25c0545cc9669e236535a2c525d3e5b0f4b01000000000000003642f6164d8e149c04a56c3d8cc897931fb62a88a40515e1d363057ca944ed690100000000000000006eefdf5a239c23d6cbf3eb0ba4d89db21c2d1b2209c9cc2f74a6e016b0d03b01000000000000003aa97f8ca3f4f09adfbb14ada9370261e5cabf467fb40c16de23c099d304d25e01000000000000003e62b9d0bd13e48986028191d48e0a6f766c88b31b0c725d000007139dd3637c0100000000000000a0213ee5b3bed7c8d2c1a0a70c61aab85f5ca94cd93616061fb6364fd1ada667010000000000000028d249190b532150da368ffa0010268afe39a04f6b42aa9e1f46e3a6cd9100070100000000000000c6afd316a11d715b1b0470b1593605ce756958f884f9a10dfc58f121faa8484d0100000000000000508965b0f7d1b2a34a821a0da0f9d5ad0b44e725c7f7db15e739169d2c75a42401000000000000006a200c878d141060a15a1a6e5a27c5ef5b11d18cf7f21ce576e51840e347657f010000000000000034db9641d08898fe93d40617cac970d6b63cc3f0e990747160662853f3c631510100000000000000d0365bd755924b260ae3da5be8a3a59865a0012565a70e96562672082e8b1305010000000000000072ae6afe31514a5d59d79d5f8db7df06205d7b9b688c3b03feade706b43cf92801000000000000007e5a19c9f2e6fb510e9f960062d9845f097d460a298f87d4fa6877b59812d3270100000000000000bc962cd43580fc2e7372d271f95146e6eb6f03fa3642fc4afe71e4b6324bca7e01000000000000006ce4c1e973cdab9013bb250b945cb7d254fc59dc7cf8149e7eca3b5dbaec02610100000000000000942192ad93f17e1e06b3ce684c14980be620afc301eebcaad9b012f4efcea22a010000000000000082b8f705c89d37e4f3e80bd45bb0dadc721ca7e0da6fbeb3f19861665ea4ba1d0100000000000000c898297afc11d3f6926ded153cf6e68c24a40f78a1c7725dbb14f45bd296c01901000000000000001087efe0172987a0422c9656fedc7c16d1466e207e72fcdbb8c2706f779c172a0100000000000000a01dab9cfbae6d9511b3141842fabcaf9f35da8b6c34111bc75c9b035c2a832b0100000000000000d207ba965dcc951fa95d55ce09c8537694bd4553253f10499642e1b665c03b4e01000000000000009c29becda95f205ba0496dfd9d3cb2bb5c5cde7c7d747845424c136738b07b4b01000000000000005289757575fbbd0dde799f324b223b339ceea8157f1913bdb780665dcc3b57540100000000000000a4e6635ec918ce60bdc14518d9760ea94874890cfc1b66b4077733f78d83d60b01000000000000000eaacf77a73b41d44bc5dda8ae14c94685a09ef45bbd61771551ebec3035d9410100000000000000d08dbcb2e68856cc03a946b6b9811a16c7b4b1fb901a5b7a43c4e3a5bc2bd450010000000000000016afee2baaecdab4d681da150a5195b4de209cb2916b2b1b0424fc6f73875175010000000000000076c45d6f657e255ce8a3903c500bd856c1aa037afbb6b8feba90276cccdc9e19010000000000000034df80fceade6a657f7aa29ddb298b6f897cd2b93daca2b7d84cb4b9e0e07e780100000000000000c84133c0f3cdb1e9e0eccb3a8bb0df7fe0302a1307cef092c95fb21e478ca3400100000000000000e2a546f8eeac716a35f9f14b7b6583c6aa02ad8261c73913e542c042f28a7f1701000000000000006aa1287bb46f6e7e34bbde1abb3b4e11407e2329ee67bf1d2bb19a4a34c48868010000000000000080edb61d916cdbcf3647bdb8b14bbd2f65d9bd6bc850c1551051b9456154990e010000000000000076abfc30bcd145278cc64b158ce61a3eb6c9f870e612388eeeb4df81bd6b6e3e0100000000000000567fda052099fc32e38939fdcb05faf8f7a9479fb538ce0e60e45793dd8624380100000000000000b8ae787b784e824f73cc48f87924ff18f602b3b46f55f0346e7f4b5425376e4201000000000000004c045a2022b0cb4f95b630448693435f0b2d1a32d99ebb70eea885cba5953b6301000000000000007e101599968105cf4d29a4af67da215d417fcfbaf738c3644ff10ef102c1960a01000000000000000c36c5b8ecfd735c344b9da74f8c9bd927c8dbd4f48a672e962720fb8ed61d3801000000000000002e64b1e3875d025647e2254433355f976d6caed731c295d456cc349a57c4206e0100000000000000fe9e2307b3dac85d27b988e968fae871f83412c4438b9fe825eae8fdc22834590100000000000000a6a53a973b86129fe08ead5a78dbe38c57f5e89b36e680f49f896f32dad267350100000000000000acd840fc6c1257b6b9c601f1e227700f3fbd5fcc53b3300ccd6e9d0c17304a2f0100000000000000689254c32464d6fc44f40fc7d92e376b3ac96a43041bc54166acc495e17e5d050100000000000000d44c526870295eac64d20d7eaa38235129383dca03d521e09bb5214bd3458d5f01000000000000009af9586554a1dfb6ae1b248c7b7687fb6ed4e89bb485de49d69a6d3e3500f6720100000000000000d21b16be7c201c0dd13e50df098fa709e413ccba06cff397fbe34983d79e964801000000000000002a1ea6005319d9ef214bef0bd50ad3cde26798b579ebd486b75cc68cf102555b010000000000000068c5e319504603a4e76c950b93e90a4229aae3da8e199ed53e2918edd6a7c02201000000000000009a519d5330cf4a81603ad54fe334337071458af9ed74478cee6c2ccf1cd8cf4d010000000000000058fe0205aa0d390eab62a20f71c20d773ed4cba26c13017328a2fed6db1c1d5501000000000000009ee966caa1368c017fbd108da32fd2d712cbd7c0ec18c3336772a5e026959b01010000000000000090007d02da676a913d08fb3c40d9ec1d122de9f6685f217b04c6eac38c3fbe3101000000000000001870795683cd0c947b825d9e76570679f0de9eac83814e1e9e57f359f0b37e7a010000000000000034e1ebb05bf47a1f776e2c45236b845360f71edda6272de55ff5222738786f520100000000000000b2db556185b0e94d012fbc5a4d254635602892079f64cdc85b3b60b40b00841e0100000000000000d45824fa2f6ba4816d388f247708c3b0d6f01b47c6d353bde3c779e8195c11060100000000000000eaa349269c25eb8df8619b0bb2eeab583ace39e300971c3769253f92127827340100000000000000b4ea5c5e2f9f39d71e36ccd2c34fd52cce7b1a7b00359dcdfc857b5a69da353301000000000000006a9df440f037ebef1b12bc88da7d8929d7bcc9d191023811fb7f1461bbb2ac1f01000000000000007cb0a32e99dd294b6b9856cd23870a87f8b12e15f5d483de60609360b6ba6f0c0100000000000000bed5cfccb46bbdb920421253cfba25786604b0869c6f764b1cc7cea20322260d010000000000000036f33aff729cd0f0d892f71d65ea75e425c9676c5a6d89ed6fc4ce77c86bb6530100000000000000e65c8fd18340a313f1fd729e26d8d9184541cec0be3929c2b04ea58bf2820c290100000000000000daea127e259d181fb7df83ed305ef982dc0e487fff133b5724c7def88ba72e6a010000000000000034e958afb64f3bb794e1215d551f682e9b90e067f22f1b9b42bcee0efd0f295801000000000000006e89b6949a58ae20b3b94bc8f3af3a17d55aa29bbd40f5cab2306e2850742b0b0100000000000000cca0e7418a5825bd5a4eab3a0d791ce63b0764896cf95550c2668032bf4ac222010000000000000050ec40a03874cc771a39dfd501e952f8800e8909a1d00d4d883b28c413f63f290100000000000000c82d13353b81fe22d14c32f376a0e2a757c1cb1b39a3078fe11206ea68be061e0100000000000000ee5c204dae305b2d113c2b255cfa8b2203243abe7b43fc8d7c1ea4d4f8a7e6550100000000000000f28439afec443885ae216c592e06e0ef8820ed7bf87cad6e48291b2c9a22601f01000000000000008aecf69a8d9fc278fd7ba1893ddc3f2dd20a327260b517a1b9cfc5d0d3479842010000000000000054c2912553089cb7867bf6d3bcc73210143b3a85b5633b75ae8d0d9b7ea12a6a01000000000000000e89677dc4a54b8d4c309cc0b729a350c1077c27107c3fcd2001260d8e56256e01000000000000000a9b8d4f0544e3d9b7d750249fab1aaeb957b597c9e3cdc20d8d7f09a7100e5d010000000000000098ef6001db21266bb88ce8ca975ec8f06dad3d813a96dc1e2f29c50c18905278010000000000000092cbec0ba5b5bc3b744e1e6d05e44403e696b3a8310ec3c6bd0716288db554420100000000000000ba50c76fb65ebca0c4b497230bb86c6ab99e30937a9469840fb8c0697f9fb94d0100000000000000ea77a256b1b116909ee2dec76e69c299e7afe0695fe548a6e262a186641fdd4a01000000000000007a49c3f1141f9b7068cc64b1ba1dfb9f158806149b45f2a2726671b5a66ef33b0100000000000000a4635434f5e6911090a2b08f0731fdaff721abd15b6a66338e9675ccbb2f697d0100000000000000b807005ae6a725ab9cae3d5452f7c952c162c9886958bc9a793a23ffb0c3c8700100000000000000ae45484425c05a86f1c806473664111eca64e31c374bc6f438a319130fe4115801000000000000001c1f96d7d0f8642c8633f7d890089e8d655e0a27a53a3f5b6d78a16222746163010000000000000002363247832610614a919ff8128996dabed35e67d7129ff931184e4ed4edd50401000000000000004635890734b94e40f608bd9291f5a0a0d5090174b3fa729ca4aeacceac9c8f0c010000000000000076b2fcf3279e1a82d99065888b090c73b397bbcd10eef7b5a1f73e63eccf3c380100000000000000b4768ab968a387f762e04de61da10699e86f4e04f2acbffa07f4986bb477720d01000000000000006cd56d8620dcdb99346101aeeb180b3b4f3b750ef112f63ca4b85d1068dffd720100000000000000f88f78aa9f4650d6217a7b4bb44a78f2ac93fde3669ef0d52928e9aa910de1230100000000000000de4d2b6a937912596d1ed7a6c64726edd4def566a79b8b19a5958cebd822102901000000000000004c81020ab3cbb2903057c3d7c1314ceb30f538e8a0cfbd67ec1d46243c9629330100000000000000fa677f196459350a92970f00f0d43913d3af34d6e1bbb2b33543bb5fbfbb2e5501000000000000000880bd908b5858486f7405c644b03c868f49d26e44d72024f1d494f663b3ea170100000000000000280a62faef0ceeba7ee094f8bd3cf8cb66877829a1bd4b8d8047f40e666e530f0100000000000000e0930906866deda0fba97f1e26dabba65f46f00e7ad955511c2716cfbdd92c6b0100000000000000284d3fc373b8ebb1af2293aa074555d53b8de11c590cd93eb8d8b94e1cdb34710100000000000000b8b14c85d7ec29640d448837fa6448f52c53896df6d9db07220e8c3590959059010000000000000036e9e7ff9396c9d613c08a68b294f54ff09d01a337ea97595a26c01eb4561304010000000000000048764b855cc68e82901925e6f8e76c70e3cc6a66abc911451df5c3a2b9773a3101000000000000008cba8b220f538efb8fb47ec26934fe47f2611cad32973e696a3b158df2ff01560100000000000000ceb06f8be04473d1982dfb1403bde8e4ae22f80c04c9d559e146bc22efb89d1e0100000000000000ba2849892ee9cee7e7d9c5b77ed328f55aca6066f9396e09897047c8c1d7c23401000000000000007e9c1a2d1484420d1b4eaddf1ac1fe1c6b7cca287f2893d9906f61753a19fe430100000000000000d82acb0e767e1e1794ae5b4bd484217c46ac710bfae09eca267d17a02ca8fe26010000000000000072d7ce28b86fd437e6601443830710b67ce32c9fd6a5d31d10e5924a9a38c1630100000000000000a42bb727cb09bc954145323a1e91e65f03f5da3d7cd78832a7ca1f8238be724a0100000000000000b07d600e3487e2712dcc3879c7b17c9b29cd2243b45f0d9343c591b89cf82a650100000000000000a26ed29f982dec849ea59023859a5ac8e452be6aa039b4fd5128485fe0d2776201000000000000004aa09981e11a8609892de6ef64fa5174e9f8304abe4e44d54359580ffbba0f7101000000000000005cfe15b2098a90e927ccf79c067ccbaf8aab81b988dd9a5fd5a8d16279e8d80501000000000000004a09d60a146bb4243ab7f5522595695ebf5ca25a15294d81754780e8ca63101d010000000000000000a05efb75d58392ca90212af5c1107c60f26da9be1f023540828963da6c82190100000000000000c047df5595b397079ce90d77e246dcfa9299f09d265c35c3f07262faa095435001000000000000004cfb64415963ce02ec57a526a68c3d082a268dc1284550542cafd6670b5f4d550100000000000000d06b093e39f4ca336ed1d82659552820708041e9d1f2c353b782784b223d7940010000000000000046006113e0de4302f7ea64b69d3d732b4cda22beb6e425c6693b26a8d8ee7c1f010000000000000080d6cff1213b154d5600c0dc20c69d859d0888e40f55edba1774dfd03742ce6d010000000000000062553cff1c441b1fa18bded85e45205a8c3e35a73d1dd099b21537e83f118f1f0100000000000000f40c59e8fd8d612a2864e055c9b5cca8f13e815f0b189b20887677ba438e070a010000000000000070803f6082990c17dbf3036ee161d7a0f8f89e53b99ce11ebbe8d0f8b2a00a6e01000000000000006c4e955fc6949a60e840e61ebd34630646c940f2f245600b858992ef8f697013010000000000000008e85b03df45aaa6dbc1fad8dda1db844b774a863114ce2ae1d8686ee3626063010000000000000038cec626320cb0b8983482b9ebd8e7f634a62a951e7cc3c5bc44028f520b65560100000000000000e07253a040b5e0b89e3e84c98e3b602d8a96c4c01ce22bcef4a2aabf83ac8d140100000000000000d088c5e979653a2e93d23e8bb3c3b21ca1f2993760068534f17f2153efc2aa0601000000000000004ed6b49ae85ccc70726fbdee6f9d36e2b9aa97591a6c8d6e18ff0a76c8a8820501000000000000009eaf28c69a210c41b2b52523ed538d49a7d2d0fb0772deee2aa7e7525484b81c0100000000000000342dcadd1a6e7de1883848f9b8b8ce8985eae587960b826eb59b498d3e87fb4701000000000000002a9fb91ac3024ccbf69a2461fc95ffd2d4100d15edf7be2d9c496237edc6c12c0100000000000000ac4df0c7ea72b04dceafa5fca394217861e2ad04c6c3a03ec95783b07376b3780100000000000000ae394c99d8a5c7a7a14b6194346aa462aab39ebd137374fe2722835e9129ed2701000000000000005054f5cb5bafb9c3e89ee003b8c6ee63f618c6959475785524ac0b3dc13101560100000000000000dafde0fbbb92c3f301580ff68d17075a5c9920e911bcee422cb325b69acc1f6001000000000000004ae767c87502cbbc9e97a5998c2f7e4f7cc9d7c37f061cb1b1cfbf289ee2b91f0100000000000000bcc0541c32e3fbe96122c92276ca696bb159eae980ca2fb2a7e86125cc8a33140100000000000000b284832c171b0a3f8b2f01d0faf1a4d385dabfc8addea7ae3f735954abd0ab700100000000000000906e713cc3de32f645f512dce81848a78311910ec52de1f0fdce4ef25e57a926010000000000000070c4745c0bc4049e0e0a780465b22109fc139444fa12370b45ab1d057745dc3a0100000000000000ee207c5d0eb36b20ed8d9611632dc223dbd16037c7a1957c284441f90a569a290100000000000000247131023f7132bd70bc2840a204e741ac1484da9534f8a6a70e0fcc0d841d150100000000000000ce132c1669d8355046ea7785c7c781f8fa77956323e0558a8a11e3b2acd05d0f0100000000000000568f565357a825a3151648d53a1648f6338832be95e8d1f093f210ca6ad4f2460100000000000000dc69c738399be3198b8ed37f66e750a52c1a313b977f02330ef4e950c1df70050100000000000000f80dfad928f55dd542a856183fad197e9a47017996f9040d34b90f0e12e3645e0100000000000000f02d13f0cfad0ffaa007cc8b2849ae01f635556333e1687bab099cec31b65e310100000000000000e0f946c3aa0274a9301d786dae93cf9dc8c874366e511c59a0eb3c5292dfb03b01000000000000005e87027174df946fa4909a46573dd45c3a6c018a2e622290a44b8d88178db7670100000000000000ba454655a5d534886c956d3abedaa2f39e2998e077db26927188d2c011ae0f78010000000000000058ca924d1a05d712c9f61a7018d3d1cce45a7a815380650eb1d93941af74d2760100000000000000f85d50ac798b66e70c4185c37a12abd7c73023377ec3c7e95aa8192ce8a1c10a01000000000000004031cf5554b7982b20484fb715de955bdb9a9c4ebc2520454b54d9d56791476901000000000000002e9882985966e92107557da1ca3ce0ec0902006d5518b54ab5b880d6524c5c5a01000000000000006289201ba70fde92ef951774853d8db592debcc3d00c5c2a6c98f7882893e67d01000000000000000e8f603d0e25496217f9222721f8f599852ed4fc8b14bfb1444ed8b787e5c31b0100000000000000e4a79219989f76bc90bd03196c8c8d9aaf5d7d3eab03b2dffd0ddd68499259080100000000000000c236cae1eb04478e052917b64e61bfce6c7172cdfadb80b5d930ce65467a3734010000000000000088f8faee116b89ce03322761ff95f33bdae4f7cf95de7e1805d8083f86953c570100000000000000587fe59190dae8e54d0213c123987704022d94c9a48c504b621823ab53eb65190100000000000000447a0c8ae1b18019bf3980e7dc9aca06fb53bff7dec4320a1f6d2ace07d8b6680100000000000000b49e5179c2f97677552b1fe5ebfeab50703e585e216d2c0c24caa064aafb6b0f01000000000000008a9cae6bc174aea173ec07f089b2a3008b297e980a9a54aacca7b2d529dc9d5a010000000000000064536c509ad3a3085bf62ee26eaf7cbfd30c83ff4539c821a70c239903327b0001000000000000002666b1602f325d718ce905570dd1ac7aece5c12978ae3b9312ae32dae1e46c7801000000000000009a01c863804a2f38b97ec31de7bbc1ece903824b513075c4507300f17f75f4520100000000000000d6aec1d94578a4d5becd35dcced2e502ad578784371d8a032eaf61aa690c355d010000000000000056ff356ca610ff17bb99c26f1575d71a6e606894d40ef607b28ceae01650df1701000000000000004a34fff2489e0cbf0bf886ae3ede29b834ea893ab5f001c16c1c07277031ab27010000000000000070d7f1ba2fa096bc85fc1df04faadb7cc96b99237dcd226a2d89399c89a51f000100000000000000ba52b5c6071f2414474c4c05b0234af224536f8baf46ceb9744d264e98b6a47f01000000000000003636d2f985ff4da3965755941d6143aae93d4495f42f0768d14437f15180a2000100000000000000b2c4c674514b3c0e55d51faf4fa3079e592f12ac61cdfa14c6bb01f96887713c010000000000000014288af4dacb175cd46ef72fb7654b2132f35ae66c92a727bdd59d3b9cf390710100000000000000b6d8e4aca12d37eb80d6d1ff130171c03381d66c020e46adfe6ebb9181ddfc0b01000000000000000cdb092eb7c8bcf072a04f00cd6794486e0dc0432ff27d923b67acca0d8a3a0e01000000000000001adea8887bdda63d02f4d65fdc968c547dfd89102c9983f60e08bf819699534b01000000000000002e7e9ea7f6744e81e60fd135682816964eee413dd9026b011a6a99ec3966d12601000000000000003c93c4b74731e528fb7e0729e384dfd760e1af764128b4c78404c8dc3ec41b0b01000000000000002896210a27af2769a85826c1db06ddcb80f4ee8019853e0ac93837dff634d8390442454546ce03020001a10f02c267bf70c464397337f11fdfc11993dabbde71774c6aaef023a13e97951ba9bd03cb4da72ff3103bd751b53f208314e0db4abd8888e2c0b66170bbbe17e07dcf49039694849255f0b7fd07de3a60c8600face3c595232486973f8818b68c966dd24902cd4fef4d2e070e189c08890c7857204aa20cbda7291fa48d89628ec4f96fcd9403152acebb81011255c4a2823ac1f19d6a51407d84f961a404cb214b6be06fc087023b201c210b759c844108fb02b303d0526539dd1d030e55c0db5a69efba6a68c802839ec8f7f86f5968889c9eab4c33934686c9736128940aaa9eb49b5e577961190289e94d58104167b98a204525165f0cdc22e2fadc6916f297c6129bb4e77d36ce03e982f49d73252c55244567241410848863c00b33bf43784a287df69c11d5912603962586830d274125ada225d54868a6f443cfb25d28904112efbc755a1772ae40028b0b3ce1f02463d2802d14e04e6f06ef099d4b6670fb7301cd8ef84b1cbad83b03312d72703d8f5536cf746b5760d79bc1c80f16db709d8a3d785abecf9292e11e0252f5e7e2eeea1bb84c4a50584d32f06b9bc8268175f6dc1a6481dbb02c26a5ae02462eb8181e017c6d22c87de1b457faed0538bf569eb58a0e3c094d74fa469e47039e163a322343466b907f4d7d4761df450b88c3daa214422330b359fb649da46a02f0f6bc29eaeb8b87eac0231d1345c164e6fc18e21d6a550ea40fd66996b8ee6f0216cbbc5345aa88c88427b9e51ced11d8c09dd59eec0179498beb251a9175a57502ba371976a786338307d80a063175ee5af605cf740216f9758fb4f29903b965630225039bd8c713d47819544a46cd1ffa18629dc28ddd8b517d814f060ff4af20a403af1da492cfb67c2d664779ada27802c702169c744bce327855c8048d57d2257c023b4d74f691424e11e4f7f07b82210269450f637f1a42972e7447f803bd186e0a0361ae0a31cd1e6bcc80e93d278cde0102de79c53983673aa2473a0d2803f59d30030663599beea84a7beda50aba046b8b0df539bbbbc56e239bd45d7aa5e45c95b003f4f783013fb66d2ad64ce4d83f65ade3155805235d521adce5b21eb9cc72b0f5026b0184b4d3a80b500354d486a3499be1d3cb982a42b95855407fc50e85f710be032416c7610a3819df31edb82f4e57b3023f71f7906a80c3c5c3df9c277a87c3f003f7324dbd8c37ae0181f7f8ed635caafa6b2d93d1102618a7e4bf570be837fafd03fbb0c6850a9b22a1afa6cfce3c727d34669d01274bf3abb2f8e6d7549b3de942031480f65e0dcf590eaa76553c3a319c7ed130f84a33c279885267941bf1525b2f023d9c835c8a6b6bf6c3487850b50328a4f3562f403f6f078b1f33c1529762fb540222da8e55308cdd2efebe0467b947353bf964118db8ec4c858a91e65feac081b803191200c32b3a33a81f21f5d29356af1dfe0d4709fb3be7cfd4e8991e2939990503c62ba79bea4e9e37acc0b0a89e52367b33ebb8f88ebb01c43b7bc5683870e84103dfc17a681a2ddb094199260c58cb70a7742df75b50e5f8b0309754ba81558da90363db72e65f117546f8603695db3b27c13003321b1a2721bd9ee9d8bf1b72b0b003cd0128540cb3ba9c9011cb38f50549b767bfaa29a0213fa1e616217c64c1ff5203b017fe3910a943f11ace1d1780929eaaebe6c91063b7018d261706cb1e154797028d89dfc8880b29308c5263c87caf4851a5d6231e5b8e1a21532a6a1c721b238003cc510ae76f0e5098679dd16b9a9fa2c23d4413bfe7459b17d0340d1692d85d5402f3f5eae783c0c729f9e6aad37f77a3d2c91aa7fe836b06a8a7be0425cd6a3b5b02dc1c8ea564d384dda70cb4acdc2e51d50927b0196d835b417f286a0d2c9f8f4c03d75b574eaf5b07dbbb0417f303e0865ec07d70acace53652950fcf2f7541ac05029fd13ee2b9ed16bcc497ef008f609311f454710350d2d1d077be56781ca591f7022ad887495decf2e1702f11a0a8c271bf0c3ca6f0a5c6284bd7e7bb1c351594f302bb55018f4fe174b516e250b37a50cb929e92c0f89c7bde3dc5203796e49f26c802768c797568f42f210e3829f70cd2149c614bf3a9a787fbc7a0b85bd7543a76c0035f56844533db676254eb2d377358aaeee53ef9555fac8fa6b5506cd753565e0802b845764fba26c3ffb2cae78c3e8b0428d9da36d907be0377ec6f7fb318bfbf190293754627ea789c71a312995b3546c79458979e847abc92c417c295dfe9a3f63a035fdcd0f6fffc84dd1e605f653f57bb41652036618ed4ddb2d261eb9ab824d85202af9ff9e7e0b9292ee55f8192399e2db00b211bd9bef51f066e8ad20e83970e9b036e7d774b08c506701fe7c4a70c3b9f517bccce371c14b1373856ee00b440f4fb034782df5cf3bf99ec58604e001be91fcefd9ef25b92c9763d630f8bedd019ecd6027a975f4e084f2a77e883e49b0d3eeb4e7a1c33be118a98879869b6d67d1766ac0341c6dfda7acc0de601aceafbdcda0d1040af1bc4520f507b1260511c60ce85a40340bc70d99bc9a71bc38a5b5d271006cfeecb461e5946fb3d5647a3624809d70a03d4f409819e0f9c76b7cd435d9411222baa60992cb7ecad8bbf7421d8fe17de2f03b0402bb047e316d13eb822461488d07e31710350d59f0fb2bff4f7715a095c98037aae94e1a43a4e9d046b349db388bdaa5da7b6d468a3d3ed9a8026d9f4b21f8a03a09c6f8c5f2d715342ff85757b96396ddfe724862cee6c5c0cc469302ba7fc3d033f2e5d86ccad19386277a8bf6c49284e8f3e9ffb7797976445eeedafeb457ffe03e462b43c589b4d9bd722cc6cb00840c193d09f2b32d09a62f8fbf12d6e965c36039040559370ea34d3294d8a42866c8a5135f907e629dd7c7999668176b19cdf1d0378c03fcd7dcfbd5653b90decf396d27d70c7fc1c833791bd65a07f24bb8c664103e4b69990421a520122ddccf505e6480de160a4de95c86772d175e6d97b35b04402b87ebeca228d7be1e83744c1c4050acbc01ca814a56431d40f2f55bef8c7880602d511b9473b42fbad575ef8e68f31240a1b965fb98bf01a7e517a91be3763664e02cceff3b150da75902b12d0f1fdee46d27d5dcdf800d346ba452c161fb512dfd703fdec158fd8818fcd1c30e68792a08862630f4f228b9b2bc3937d24d18f56b49402db696a131f7e9d3c0fa1aa981ae88c15bcccbe828b899ce7bd14b45a70ce70ca02bb49c0ea2cddfffa87040b86fbd7582bf70072d01452ec052bf6800425f7cf980207201ad43a45731cc2e15df59d8b88ef934e1f7c7ef53046c8a7c8d2229ea4c802d22d007bd629e628270f769201c17fbb4e89501df44c321b9479c63b7e7981d502c212e440b9b2fe64b83513b951d7925a99d20be7c2b3133e2802d9eacb689857037bfc227ace852aa400d547d247869d9f49d9d8df631179dac66d4026b39e304e02ee3245f8cd70e8d8c4da566956a1d72decfcf65d69c1724a3f7465c08a60d15103de2df067f86e73fc01a5e202ae66fbb69b5e8ed54fdfb9831b9dbb8d01687693026e3e5e408f92c3ffd0ee17b01833455c99c2542531ebcc4f6c2c1e495bb5cb1d03d33581b35d4cb57b27d63db1a5f974d7f4ecd172746db50d5b5ee1789ea26aa402f46f3072e18b197ee9277e87ce2018074905a25e1edace3662e9a53e8d28b90a02711b29abf4f72828888f3ffa474a0708547ccd4a30a380fbdde9146e15c8f88302d6979517a0905df8e14d6620b3218ad3608bdb2f6dde55b2a40745638f4a762603a07d73316b5d69ae51c6f0c82f31ea71293e6a12303d4dcc4a235bd8cffe21b30240e0b5552cde36d369534614947b51c4e1ebc447a3933942ce6cc850bc6beaa203233f724e5c076feceba9b52aafc2c008a7b3210f6b1bac6fc3d563e4dd2275fa0238e658f60d50fd38b111b497c7517752fe520cd6847e31ccf350ec0563f19cb203420a84092901e6691d56e96babdaf5be5ade9dc4bf31425bf40b57b28e76877a02259d56b4d2a2a5ceca43d6e63257176bb1ba577dd8a4ceb0161b0662fb8092a3025953eac03cfc1530c6a4e55134355259ca7ef13d420750fefd3f9cfcf80c36680348f5b026e76fe5b5f64134d5d2be08e21460f0f11f8eee5f4ec0ad27450e540b033135d6fe84a935be84c0fe29cd50f9c9c64cbd92b9e82d7beac1e392c207a93e021dd215bc866487b5c1b7e24e1bf0f385605b85ad75371de715b31234153d2bd903aeab2fd32904bc8beb99729e18c821c24148154cb39a9607572eef5d30b17c4202db9d2d5a6c000f0ed34c61501919adbeb05751ff44db1fcb7cbac83c9edbd99b02b832f261e6d56e6d896042fd63d8786e416377acd0c89ddb325f9a814201878403a6a278149655f7d3e3999b3e1e525de5e85ee604c555667a9d243afc828c226803dcfc779e0711eff63e50466cf56ae17ab986725bba8a1c4b5301b9915b5e3943039277139e65fb528a30871d34f7524f447655cb0a395e3c9033cd353ccef5e22d039f429002ca2930adbb4ec93e59761f0391736d99ee566b210df6636fba8af07003e2fd3546984ef99e11f5131ce2fc50416fd01ef1085814a9a4a3f653c0b367df0389083bd3be2f677cdd402126915500a4ebdaf06279a0b77a4f9a2df86603a58203c896b1c5f88815224392b07ab89962ff4b701757786d706d25147bbf53c28aa4030e04d5056f9c8af39953d3a151aa9f09fe0cbbe80d831bb3feaf21f82699d90c028ea3972f4013b28f62a98d3ceb0846b7820ae029dd31147ca4c4514d8c965bc70269282389c624900d98c51a1d3dc240dde7e2f51072eb533acff24993d29f108903a0fd77c3aeac10eaf28645aea0e71eecb7746af4930417dfa2e77c3ce98ecb5b0332ca45c4ffdcac76cf2a614c471d80582b7c3e39b14db449fbe90f3ca745d31c02135f8baa115c21725b2bc940d03b3df781f497a7ce263521cf14cc199cb2e9ec0398396cdf0bee48cbf9f4e37c3668e9313e5697ba07098cd3b797e3f2e5c7febd030aed07037dc772a641608ad7b20e2afbd4dcdd26683472f54fb4569418e3b38503cebfc1d0ef142f4b5ce1bab7d9a50459d38d473c5a8eeb46dab784b005eb2b35021c6b0bb728902ab98c5299df6af49e6c6de584bea5d2b95f8958b0a39fbf4c97031430f258598abf4dd902967e6fc406ecb85eae98f031971a1086c2a6bfc7205c02fb4ae8cebe2ad69b8b16fff05db0c4270484abc9017ee856adb7d409ffa9783b026dc21ba72adc7676f05e6f29045bffc4f941573368d27efc395d8001c70df975036d3035f9efdf2ae47135ef1b8607e21d06a8bee3744bf75f06593bc4804e87e70291494ea9281d3c3282839d84d34112380c8dc5cef9da113a964a5e801fdaf0da034485414bb440ff725d96b629f7e6841cd60e5f884c26aef0441c7d9fcf3d4197033152fc591ec2b4670740dff192e20c676f922ce197dbda27370b7066712e0c34023c77218e35910677b32f9d4dfe75594777d3fa8d99b638f10f3f3c1eec684b890349e1f6b283b4f622912e452d750dc18ab18ebb200133dd15b2043aeb1a3c3cf5033f69e0b66e4c64cd8b7766c919b9bfd8955698a48ab551c1eb54e26a829fd49602affaff902542bed52ffaad910300f72ac9622f27e4374a17a34f834e38fbf7fa033748459fc0807657500ae4347333123394d66904d28c48e507dbbccff10a08e202747be66a3368308b86cfa40f4172d790d9e44dbb23328075752d0a733ef910dc022171cdb5521f0d6f436501890453c1ed2a26732ca9b60bb395e3f7c1c305e2f903180988758e4735c26c48d772fecdab391cd5a4221e004b680bfdfb3cd8f9aff7022def1f764d7208fb5156608d76dbed2c0b4eb64006d7e670d9bb2f71acde69eb02f499da32a6fa9602647d56105d8fac1473d03ee2adc7dfba78bf97924e6ea56602ff0b26e4b2c672c21233f0ce03e2dffc762b6589cb5820a84cf5fc961e7887d3029f10e01eddc2193a09406b60bab950a020ec5cc35a32d30ba9f92cfaf136500d021917d4efd86f55c17797975ff4e9d19260fecda85219aad5a7861b5fe74237d302f6f486e479960d272cd4bdbf02919a004d8344ebc51bc5cf1f5c72ec8e6c180e025fc9d5fcc522fc0297a5794481a2a1e1f75bbd6c3fc15cf637042b5a0750f26d027ee782d167aad0caa07fda1a70a63b971527e553aa825583decd53c1c280eab7025095f3828747e82061bf7fe1b6bd545d37f179e9ce70c71dd088f3361023abb60336b5734927e85af86efc4dfe012ea51d6e6eca0a840f0f004c70a70e41891b7902c86942a19fbf4c4ccae0efc3f030fc1dc0a9fa4351d0570a98cea04ecc13888303baa6c9ef1bb73fc22612a3921dc7c2798a15b0a73e94e2dda24f48d0be514b5202ca10d1a2a3201ba11793f6e261fbf8fc965198ed4cf33966720de775542a32ff03fb16946daa10b39aa9a92c917e9f186813dfe0c40e687043ebc7623857ab989603d461d1190e4aaefe66ea45be2a5b44271bd3dc553f1cd8efdcd554b808c116b302ad986e68a6b5c86116e7926c99ac46f48a73e5124dfb6a13b1bc3345a1c8b642036d96a18b2c568613515749b31b01e364dd43be71f20746e2d2b23bb5baff71bf029c8abf7ee90218cd213ddf0f1bd7818a5bd16af659ffb9e5ca6cd69dd16e4d1803c71f9c92b23680b5a51021ba10f530a199ba01405f35cc5604936cbddaadbb5603714dc2ac60e4e52bbc1706816c34e37a0aff6a223f37c97d3b268f9229db5287029c640f582c1420d41f0a06442096dda8beddbe5e0b4590baf8c79d9ba5ef65860342cfe39dc868c87694e15277392aa799ca4b387d56a429fe41dbef3701dcdbe70384b7bd5497039709f64629a87e680364d657f49fa2568e548af4c14c5a4aeb1c03a5d1ccb400fc7ac6de70d702381377614a5d95e8df54efbb064e479a0956a21603fdcf4affade0d263f476f6acda2e000fae77966ae54b10bdae7a80b6cbb12cbb02b5bd5582e31ddb1de6e7d93a8630168abe116d928f6b59f7dd6d69dc151c56f802f63c734556eec8859c66f16653b16e6f3f862cf496b030b03da07261ff1541ff0262d101229da98353b9815d7d1bfb099ac97fb488adc7f8e7f8cfe2c0a7f4be4003307ae3d244620ea42f39e8432883dcafe38f88ca8f0307874e1338e0256866100395da539fd398abf1d0989e8f6dd030293e36d012439626d2b568bd1f4ca2855303822ddbfbd7b8ccbd9f7ba7b756a1cd2ba2ff25d8c42b53e86fe947e6b474a9f503de3d198b3546867a2b8b237826e5fa11cf666bccf81c3c35cecffa04b5c899fd0392b7fcbb880669007dca113efb1a0430b2535d4d02828f9afffbfa670062c186039690bc8240c2458ac6ac7ff62e38f0c03f694c65969e013da84d81db9096764e030e4e851ef7b952a004eb8ea53fcc165fdad2ef0b7d358a5a9193fb5687410174033575615b1c89223f2c0fbe4b0daeda0c84ab490d62e377cec5a8561d85135f410370cea17e248fe922619708844a66d8d081292acbbe9714206ce825874f4be0ee027b54de4bd299413709d31c0da16a3e971902c03fbc90e52ceb8e9dbf0e12d8a002f779ecb9b6c2b9023e46d8108cdbe01a9fb1c84083964d80d26e64e7e166b64f02b02beb8280e75e3370aac3315cea86dfd2322c1eab3042f91e6cfbb251094bc10260857c72582700d0b4bfc621a81014c830531bd0d1d58f13ff47f090814e1d07038f2f2446a42f724d28deb1d2d238b90c5a5517a707d8135358ba638440494da3035e83c6cd83602fdcb0a2df6f9a4778c2bc3dfe81b3ce5a856d4297b8d5d679f5037a8bfd9822473fad717a0de897f521adca691739ddba96650e56e960a78d1f9a03a98e076c8040a8d8abcbce269f05b967e56059cbb9db27463b8c0f1024f3d182032f01ac2605dec6fec2c196fac2ed109bdfac23685b4a37004b54719b760bbb8b0233a0b244ff04a3efe63c59f6e8f0a6a12abafd698180dbe7da30840c4fd6f6b9037636a3900cf0e52fc43dd344f6d3fbcf621d863bc19f4f124966bc273e03970203b806e6ab70955335473cc7a4c7501d6588204215952620c002af2f178307897d02c497e1f30a864e4101eb8c3fe75843e86fc5128217282005cb4b826f72b7f5b40388cedcf743d5eb011b509c6c14eb521bb1c8349fd8956748ce0d10aa2aaf1c44033be660150a3f578496d970ab8541ac74b46e27a4c1d4789ef1183f851a76a5f503d6f6a7c21a662366b950998de587ea4f419d9835326b73a953791dd20c83a07903dd2de257dfd5b36b3220966cd13f47a0aca5a919798dcb11ee73f5f34ccd824803bd9f2130bd6c462808c4c8d99a344b577cf8f8e056d42767f0c7dee76e7ffa7503cb4a793f9c8b5ecdc166e438fae4fefe86b01a99979b7be6e9c9360e34dfbc84029a8464591da8032ba285abf5980a7aa25070f5797c29607eb1cf6269a523d5ff02d27348049028ae0903cdbc41670ce8f7e725da4b5474e0db4d1a00caa0efbc44024b1b43b9ddd8a8abf9bd503bf9b42602a7ddae6941a6c904b8e76b7a3d6331da02376bdaf0060a0d2fff7e25fc9f9ef0f339f5477ec208050c96efd76a589b56eb024ea3fb5dd2cbea85d629953c2ac9af9cad20c9e42292e99aaad0a64ee3c3673103170368985b4a986a5f757015c3ede46379da75fac2c8a3b6a0479702b6941d8c03f4780fda5536a8a40e407445733393e04e98cd67c34c0fe4a3fd8ae229515b50036ff8509550edd3281a2b4216e3d24963f57d8c5a02d9256813198d8b193fc9860237864af19c08c269d016c8974534d15329b4d590a32a3bf6ae80d728e1d9c757027755ed70889bc08ffd12d21a25c9ceffa0f623fbb503bdf5a7bb9bb7271ed63a027a801289fac2faf460a1d88d6b1f57937fe63e22fc3fbf4b16421fb42142783f025db56b345f1fbd350841a312f1b1895ba4e7de01c852e9ce4b2d504b8dc867e102b9df1e00a16f88b68d01063a033061fd9996ea97f3c49dd51083df3b8623dc110397a51e148ce43c3f36bb5f72d45be440ae519db686cfce31a92a264fd70b5ee50372620dcb526dc02e6c626c659dde734579671f99280f055d79ea743e7844f32e02af0157c8f049c32ccd628c2b439d1605952d2c772ab9fb4855fa491e4f499b2703d95cadca65546f0138e392cdd241eabac74068b9c3ff9f77b2b03d2712a7817a021b5bb4ff483e94b005a19d26536eb11c697d13ecd6843e463dbb4315311c21d702948f5a354a4870ec693374469226872829a0dccfd426c89ae078973ec2e9531b0221dd156298249902ccaed3e7389255bb596eab43ba972b0708f4f11fc32273d203b6be2870e9e8d5838c8879317baebf232cbe7eb4ff1f956faed21907c9085fad02e4440fa60f27d59c5feb41aee196466e5ceb9ea0e75a9c4338b8b9b4afc611df038cd2d1a66a225a5acaf2d2e5a8ae674f1cc01188bcdf5086934efebf08820b0403213b2587eda7bce21b0ceb1ac257e00435a2ec7fe0c7a6386f9060f28bdbe7c5039f5cd13aae23adf43f6d682dc1e12a07bd06222ad0e7bc7ec599430aeb884b7d03ecff4b6ad15cd599756c8f6a96b0743fc0de42ea92ced6f7387fb3989035886503110f227058ce439e1b5fe57694663015f4bf1552dad5b9d4c34128abbc8b2c610378e4bcf8b77fd72f8060572a2b60c6818ef6cf4c23b76646148769e48a2b3348030ff361cb4bd2b345d05446595014a19a2d73f74c08a5b6b842cdca5db4d46520023ae98bb68e2963b1bbe5b929156254b9514cb907b679a467e51573dc531cc32c03d6b95b662602561cac1d557571483feadb70ce08bef70da7edae072b450ad9570213182aa923b641a7a5b293c62408e964b9e947e39030e5b458b39e3e3ae7a3fa020b63578121b05f3a78d034ec504e4f755bdde22afa19cd2d16261ff82a2d6d960398489e850ad48893225263df8d40a0b82116bd97a2285cd9863ee79c12c0b68a035d0775aed216af63ed53ac2b4df3ed3974570e9fafe8d5b9832deab9207000ae0276fdbcfa422b99afcb4a8d227f483dc9c00accd743634a3142c5b5efdf84f90f02b726424655c0facd5237fd3decece8b42871a363f1d10cf1819a6bc6730bc5b102cea0cbc03cf1a0cebd0aadad06adc2eb12848ed71a617d860d6a92f970d8bc1f0291d07732eab27a9d00e5c8869297517a84aa7a4864a8d538f62136ca70e9cb4303787e86a2a510b50f466584280456ac9300cf25d50443a3d3ba96ee348a24f2b902aa13da13009e92d2f2b016a099ea77ae0651cbad2d6ad7a9d8766e92b28d17f6032d5c5fd3a5c38d6970e2050de6cd4566fe2ff448b0d70125da0823e286dc320303c532a55a69ec1c1bdb450c9fe339da949dde2d8013171395d19190ac5a15559602e8028cda1538a941a0b50a2606477a413b3e36c1371bcbd027ed82ec506d75db02ac931aea34808ee3c016bb15e4b96e119345a06a2f7a440350294f3e39a48b0c039858bc818ef66097649074b53a78c4e67529ba68a2fba595c057b6b12c4e9b190203f33f184d6eedbbb2cf64b4a2428d8cec390e4a7eeb81dfc82bc4be8825088d03081848ecd309244ac8be5d30bdf64cbe77062dd8025381f3c47902d618848bfb0331b5c947932b20d95dbf17fd3c470d245cf601efad272300e4f7174130d18fad033c3f3666bbf3e92a388363bfdf684f20c0142f785c7e2929c7ee14c4eb041f2f03d277587907b927962958ed74e02f383e1df50266186a56cddd79a2865e2a639c0273a2c71701602a9f2043a3731d24f60f42c4e984409bee1e3cd694ba41ef5de303c8a6add237bb3030fbadb62bfb3027ffed95796a5a03abce96da3d1161b0569f024f67fd60ce8f5d6b2e3203b9e5f6bbc58d236e89dc4eb1cc2dbe3144d7cc033702474863b782e3a7c585ea476cf060999eefb4cd018c1bb8fb573fe6bd2087550a0382a27a62fdb6911cb05f842a6c127d1f602f03d8e1d43d54157832c7c336c75402d74072f2f3bded65454aaf1ab9937778d3d8adf6451f77d765e3d38ed27c815103e5913d2176efb6705bd75a1c7a464dc66724e94e3e28b906967773d8068bb63802b09cd3bc9ed0f7b70864290b6aad96f79e3bcd567fc3940c1cf3f720135e33ac0285f52354a9306d68e1d6320edf9558418686c566405fbc966ef98a656853717f0393a69da4f80ef8f977121be9ba932776bad373fba2203bb3bf6d177dc2ae5c6f024aecfdf0b9333995d93f2fd65229b1ee3b47fa464ff640487244dbf97e323d150212c299de052fdf39dfa1854ee43ae5e279478e165ec7f76cf9869ccbb349e9f3031aac719d3d6d5c9590859e9933e250f6da0578f3d8e989a701e4b8fdb7897c0d02e989a1398d79fe3416855c587a5523d6cc2a514ff137cee5fde939800a390b41021bd7f76d28b51a330a87cd9a441eccb3851fdca78fd07daec04cde56324400bd0314724d3eff74d1e9d0e730c6923d5aa747f8f4534172e01a70311564b829719503565e9b7858ea4b4bef967bbc616c105c7c2ba8a2ab26b722dc61306ea5ee0ef0023a09934da5b33ac08d056d9c4fa8c20b4655b5807105b9d7c9c4c2540bc39094034c545554a3c9d8fd4d5be61d8fd657fccd48fe67f1800ad10fd1ee9922383084025b41a634bb6a7cc01b8218380833b066a22800a0a49af0b2e658c61c304757540306336057bd18d8ba9429d96ece61ac49aecb6eb9deb24826076f75c88bf30c9802bdee2716ef94bb712f1fceb156b64b597e839633070c231013914df6ffb3ca9c03999a7e30dcc0d10ac512f6084bf79cf81ae5fd01b79bcaf0a53c270ca9865a3802fcafb0df840287a616a29147f63bd48c6e998edd64709598f3dcff8e6bfb925f03e24ba021ce08a8b5263b59f937392a15fbbbcd1d4033ac30e812d23bfa87717f0385af0902c2df33186b3cff6175b8242f0edeed7dd164e1f15000d766118b0e62032a05784fbffa1ce80cceb0e3303ce7978f3823ddf8cf0878df477bfa02f3aefe027d00054e681ec2c4c80898816567e37e67c5141eb9ca33c531bf2b34ddbefafc03f0d1615f5db8bf29a53bba638c6016e4d427bc9e431aaf0aef0147249ab70f0f02dd388f11ea748e88abea3bec8af450a2c4633e78303afdec27c894079c17d04202b562ce820666e3d7484cbe953cb70e37c4c3fa9f414f0a444a4d09271ebd58870324de150d2c26bfd45ef2ce8438411dafe1afe4cc515def455930f7e84e9be500022e9c6e5ba0fbb18b4f766a8321534d42b5d84453b1ccb8f04448bf057305b49302168b803198277ab3c47f0c751e49a16fe5299c887d6fcd9c0d43ec0996e27890039a8a1d1d989786b583e9743ae7543118337c6d1eca6c2d4d9b80cce50431e4cc03f48e168971853ce513e1b33724215aef528533f1af8ddaaf7746c68662e64a6e03928705f2dc40ff323bc09d681ccd478311bab05f002e28c3cf4053473cf1fe0a0290cc4ac1c136fba9b7029a3abceb6d2520af30055cc171cabb352053c45d700902d12ee3198afac4b88c11ec0c8388f66fa6a5fc908bea728e6bad1ea53562bbc8026431ffc38231e19bcca1c2613559ad82d30b38c89ad55bac0918d88434c8d455029d26e3c5fc8f020687fbb807e85c59aff8bb1d8f38a829a3b106e742a26053ce02229e612f3e01f87592bea6d2b128cf5bf4110b08fff32b39a56f1adc91ddfe3503e133ef135cec59f4096d9fa298f2d9c98658fb22e5ba44a493143a525709c48b036f082e6f1c6092f989a8ba579d18e7ea202c9344ac08b43c19a568549e4846fa03c013e3953fe4afd05453b95fb4cf7ccbf4b4ebcecbaec5a2612efadb4c4b43d702155b37779d14fd0a519d0127ed538b7a4530ed85658b622644e37c3aa2cd7106039d97af3117c2a9e8c31e73a3a5659e6482c855ecf218d698735b15368377da37027c9a679ba816a07f934f79766fda76daf2ea0bf8674a5114ec3ab093f6ea95200293b2dfdfc7c630c939f41f343643e23853abadd729f9b8def9588377575097de030a96790934505a67dbd6b77fd2a1fdd03947fd47d1a61d5f974b6518b88aa8ca026ab22d7514cb64ea7403c252c88184b7a66e25b1d14b26664762a4913e4462d00373fff18607eae5d73c421365abf9bc175d766db253b66832493fff9f96701900029bfd3d135420a05f37bc1e3ff92a728c6f24254a048103b6474440702a117648032016e2a5c0b2043d8c823817c932a3ddb8e2cfa7d517c4b2adc756dfac74644f0254dce7dfaebd8ed5286f7a7c45ba7887ffaa2683ca96e996cd15dd8fb8c9a3a1026b925feb4c7ceaa1429c6a4dd6bbce78e4084af87eae0b26464819acd3e7f17103e332c8e257445cdac6c1c2d04aba4de9df01fd0e1914a736d53d8613cae5d6b203cc79c1abb43c634b2c3a4cbb066b974e63239a0bea76b1abd4b69904f6b3cbba03c9746c776ac52cf566e9667a887f7ab42436875993570057cd311683f84082ba03c4d6a2ab2dafeded30176c066f5bb2d146dffaf426131574cb739e25658273af037bc202301860292aec38e45aa2c2da01ab18b224b5a36674656b32bc9c6f6974032eed6cbc292f398574ed52a547b3b6499378aeca63a73fbdd69e4dfb90e03315038f1da5d4b48357680e56fe987453d2320b9f8939861d7716988b8106935e9f5103ce66a50ee7004963bd5ee872fc3f754235374a860b2e470409842679a13de49f02c67054400df926d30d0c6e4d5a9310080b80b83797ee3dfc165b28772d2700d803cdeec64f71a478aabc44b0936050cb86ff34356ea813062c5349c7292b361484031b1ff8ba466c22cf4124ea9ef373008438240987232341720d557a43c6b8ea130249e4b7299e79ab3fbc612b0cb301f086b2376f85149c9d740de11ac8bc48c7fe0310273f2514af87c325952f386e68216a4f3bc8eb52effce1c95fc7a316ee31a403766986d9136cb5cce19bf6b736e76b3f18ab675c0c84699040aaff74b14b1214021ff27a63354f2156a08c95f1f5987f8952f430c8fa7596f2d62c3f2604ce0e98026988f722ebb3b6cf96912b47c380db15b00d0f3e012640a68f1e1c3c27daff170210611912a3ff7723f24161fd7c0003818b9c56b0fe8898ea6f2a94784701591c03dd506ffc18e609bcaabc372bba961a0c98654b57889c91fc22529a808c22bfae039171c7391e3e263bf031fb952648ecaf5ad3321c9f7ef9b820bafd862fb896b60273ad5cce648603333029b983cafed8cd204ef1e5a622013b0a578395ed13acdc025229395193d9267af238890816b3037b940627b61ff9567785fc11c5081e7ba4031182784b4c2b0a7c2712086250f5bb9f14696baaef0beadf1809c179ebeda25a03f3a7243ae7b58b5790c521a3847bd1e33d3af86225e44ce9eee801fb256638510202182719e4046c0f73be52ae9aff3ede7ab2614d3d0e5b5977b762bea5312dff02b1379859f9722426b585ada4d182423e6eaa351c8f722d3a191bab3d0e4f538103c75e318133ac81e057531054b78d09dbe49b8d02bd04916f902c1b668b645d1802f7afbdd58baf502486fc068d0129e09ad9e3965c03cec7daa61e11c35585181303ad6e2623c9b34b2fc551ccc49ebd8b1edbd21217ca2541aa54d33c9ae606e0e1031a95dfc8260182232d39c38df0d0f7dc2655652e4e8388c8e1f35a80094182c703d7cb93a6a4d1fceb4a2e64bd825bf98c0552e74b6004c6151bf79b54226d60f00267146b980dbc146a01621327d4ed0a4848d6b50af112398090698fd537fe60be032cf5ec6d7c14b5d9685173a7e7336dfa3e48694395cc64d85a99d5c8c590a04002ef75ccfd4c858aabdfe4f4eb44ca7fc5cbb2ffdfb641808394bb5e9057a5c492033438e164107a5339d777fd572ce3d618c49eef3aa00265e06515b4648a454b9002844d7c6090ea7290a6422412f0ed64097510d77b34a54000e85d1126089f39cd03d09e48c7e8a70aa8c45872c647ccebba1f277b453e250dceb26a149d306bdb760380f578459bcb16b28cd45ce657fafeaa3b2a5dcd094002045e1d5b3d8937dd9702ac85b5b22fe86ddc0371366e5fd531409f40a3a211c6ba8b1bd714814d190ee0038993e4c82b39b1fe0a32a6980c2052485813f3b8f9b001cc27cc1e68b040d39a03c18ef4456179edefa4d2d157a96837e9557176addcb3c3ef432a868fc17debc8020ec0a0dd3bc4690c0dc9a06c7ac4ba039642dd3b758c2d098914327b6eceba2d037e239aff9d37761955eaf69488f3c5f162630d63fd558b2c73364c3a4100d7b1035cc71f25f004c6db192a1f7a506eac1ecbafe34980090d28fdab13e74c3bcade024067979062a2793f3e041e580063edf320e4280e777ef9a8daff4dd541ee8c2d03b357202adc1f88769756cd592d336de59e895d78d111e56431d0aff32f5f7a8c02bef11f164fb51d3388e51a7936104683747bf7fb8ac2126807864b947314b29b03976063995fb37891feaa22ce11e412b2e3808ca9264e330f32b5fa36c0eb9fb80397b9508138a12004d06d7d5fc92dda337b13999bd3f3792eefa0e625ba5f2b6903387505e61165e4c92b6d383b7d54b5eeb20888f5c9c1d99e5f563f426fdbc5ee02002863dfad02873e0291fda50f4327e3cab2acbbba5c9e824b1a5640c25bfde302a3a2f4b01be9189dfd5f49f57b4a80ca9882e3b8d579c7cd6ee4d37280c135ce0203b97c690161fc55b36622add37ecffaebd4547c67400abbfbaf0d8c4fab54690287e04a93a5476e20e935bbb40d68de127c248599810f6a741961a18c6e6d0539021f5c7d3efafd13d457905de385de8a7b1171e88b6f0f3a088b098e8e1e31693d029c6553a70c2bd82335c28db6675cc9a11127bcc1c20301b7d807cdfe654e5cdc03efeb064fca0d517d44908b523e1c8c8c7f3257f6c9f538d9d752fb10aa4cca30026ad131c4945614dff42bd46b8fff7fc3a8cdbd7eee54ec4131a2e6423f6320d202075fd8f9d066077b91321cc9d19987bd5e65dfe36fbd71ed57262858597d0fa9036e34a0f270a2631a005f01ae2f2c27930622f13ba7630291289f68d737a62b1003945653b480096aa566f180e68700601d5d9f1cae6c4f17cf9ce14a92fc5e857a023ab8894eae6d60618bd3e5bb2cd9a4e11f6f7671ff26c06c50a5e063cf656ffd02e5b8efd48204a30c0ff7c1643091f8e830b356ea085dbc775223fe68550fcbfd03c6c34abf430413bd094d6dea6f20516c30f4ddaf2deab4dc7cda12e81afa00b5034f10d1a808256533402a4d0278422d175759b141c426ab2e3d3d5feb23972ef6039f6fdf64aa543bbc8a4705af6c0149b203d02cf1d3fcbaaed52647239a2713ef0388a72b74feed66a5cd58b8f64d3c8d325d8d6b72c486a44c5f6270d55a174eec026ea878d510e98004b51e049e7722bd037d5e34218e400bf30ebdaec317306026027a16e2efad01b294073ed0ccb6e89cfd2cad65c1b41453203accb27d462dbdb5024b621f5a03fa7074555b5c41430a596922b1eb2dda3eba5873aa9e939c960ff903cc565746cb0d50c9182c1a18a849b171af8c9f08d10be647f4a203fb1e187eb802de5f446f39d7edeac03e8ee33918826d21724665f3ea2770e31ae2586e0afb530363ed90923f02afdca0475da74f3bd515aab4d0f10eb5667d2ceacb79fed82db703fe31ea0d558b9ec1ea9322bbfdb1f566b3f321e339b6dee3dd4ecf445467fe9103f95680e9555a9e3b15c2bc5626f2e06744682373f806e7ce41dbf8e5320a5fcc03e48c7453ca219e17d68cfefffab35e9cc93a1ddd45dec87ae7412ed2816ad47f022857b60a970db62eae3e5ae5594aa5bf0f2e6653a53526459d0058fad6a4e14402a14d43d07d059d6875a95dac5a170b500029fa6ed1f6960548ead211d34df17c0318a0301054126429dac79df44d030d7500898ce81cad0260745e1e9ff500eff60215d9774ae21d12917aeb1d21445fe6fd39cfc654722b525ceeb135b5a2ed7533032e43681fd1932081a1ac918e7dfcae5153965657edc5dffd7532b34c43a93667024f6d68d9913791c7d5ec994291860a9f79c54f7343c585665cb4c16424f9ef3c03d12372fb975358bca93cba10ec96dc0fd35236f99022ce10181e0721fc44f981028eaef6c34eae6987141ceb4d74f2d7c85f4bd2f1236bddbe2ec7ba136d839a24023010dd5f938238f5e156dce32b38d9182dd891f202916e35081ecadf99f6d3e203b564592e77d890c8141f28f2cee74265e4d7defce4c3f016d949e9a0caab87810279f7c28da3de1dfd196f9ddcee740c75377e8021ed437622dd9a1eba7e7bc2ed03db285f084d9a930e59974b227e6c2179436924dec76a0ac898c5b55bdbf566e602b8874d90371fcfc3b7ba33040ca6bdd59d79ada1dc4558e1e68828b987f4ae260230ffe12c4f608a7aa86a6de60472f6a8e42ba27a99fff95c0c51d96b175fe8df02d7ecd62ba38e30ae17443ef7f3175a242386e8d1c3bc576649e3c0005e1f4aa9030f44e5847f8a810165ce28f6cf5d701038cbdaf8ba849218c5890200be0e29bf035b58879dff5d40c717860f010364acd3c2d866531a9d7e8f2bea98bff6094e3202211e7c5a2f65d8131d81d1ecfd9447d9d9ae02cc63be07406cfb8c72194fb2c902f85338c193a09e8ba5ac016812ec6d8088b101368fde199aa40bc33d50d21a5b03c1f72fa69d0f9fa1f96ccf3e83947e0f86d10282d8b5345ffe02fdb2da63f46202fe88fc293e429bd20dc153a1cd8bc1a2bd7fc49bba7c678ef0c0662a3677776a035a861842259f541372e8dbc9e42dd5170f66518b0123b447912793919464ef260332fdc779e2c9ce727f7c71eac53c0ffbb005ca243f34bd3368110f28878b6d9b033eeaa26e8cce00b2f5573cfa97955ed62f8e1fda5b0fe74e0bb756aba2c234a9034a471a232201fb98f7df59831226ec6edd0a7dbe7e27512cd3127558e46575ff030fc3b0cff4d66dae2f6c70af9d5bf0b48bc93ebfaab0b18b01707782ad853580032dcbc73e399ef4146171a94f07ea88a9308a1a000dc351b692e0fc516cc87b540251d860cdbc013b9040d8a3483b5cf81542d920c4047b385ba043d59db11be4a903f65a9bf5f7cfb12d04e39294403a63d8b423a7715c20e055a5a1e1b3eb9e0f6202438c1a0fcd1f5fddc3f041820c808879b21b954d90ab5d6a4dedff8cf1451c9202911d84b821428c35c3654a4f92861d49a3cc3bbbc18113763b737d50ac76dd94020d99d8fef0ac3b93ce54ca6dac2ff6b8b145cdbe77015c64d87792d0cb07f29c02a32d77af9b860f23bc29e39745250cee5b2d1316a4f85b7cb2fd0e1fab1aa47502b39d490afd7f66ed55cecdd388c1d982b9c5e12850d33526fff37c1e2a09978502d49ddbee638e3a0d3bfcd527c8cd88f0d800617cffcc7f802e97d76ad0e95d5d02a2a9ed27ca5017f1e6c1ef38d374b4c5804ac6341b0b1bb2724c11fa42ad3d3202dcea63880949abaa2837015f1a4c5ebc7ff5faa20b4142cf8da669f90f3df391030cc02d78d7e2d536bcc1e22cdc44c82d1aac5491b4c2f65fcea9f5cba6e0e83903c1d36354de845447c11b2ec6a3ee5777a43f4ce089273220e13a63e1202a2d3502f15bc39edc4de479f57a10e3c2f6fa1fab4471cd96798b6b529fa967f222454f03fb1eacacb9f444110dd801d5f8b8224476be2ff5f6c11e77ea8e28c70760d12603c35fe220e9e820262dbb757e2cdf8a6f560f044445bc6b436a27fa5d3717848f02c6cb452125bef07f552075316f6034491cd4fdcb40d2bd6557f1c3b9b602122603dc2375aff20b0585bcc2d6c0abf538f671d022921cbcbbd5e4bae3f1f823a8ca02cb2546ece9eaf8209ae3a965292442d376893f1c1ce352faa704b17de1c7765702817de0d1e768650583adaebddc45eba6ff3b9515f79de3d64baa4089ed7b1697021e513d127bab3f879130c42477b495a56fdf6f2ee190aaf22010cbb38e842465021b034be1547b918693a31552e0684982df8b07acf13a07272c52b8c5c4fe7ed702d5ebc1152fcef4226a1f5dc07ff3aa48f01e077e973bd95162cc7ac06dea8b960304c1e62c78c1fca53380005b027cca8e40578fc4554c4074bcad805928191baa024fcc6bcc1abab45e35a5294546d03e92dd689cfce1c70ce3d7e7ab0b03665abf03231d4350800768898dce8b99bc24a45d71ff8280656b4f7e58e03515e621bc7602e62a43dc191c572d7ba0a4c4e5f4464f456e79d2e096dea016e0794ef6cf382f02c0b515fd64f56cc5bb91f752b0704a4a89135a095246e31a052e2ed491e2d62b028fc59ce1587b0341e6282046ed3bacb333c26a3fd0abdb9882472a0906bdbba7024775c7874091e89708e89ec3e9cd21507975fb78ebd273865dd91779daa08be103bd90b1cb507d5e2d9785cdefa2b452a92ba9eaedc248ebb6290c29ae177c47b7021866bd1926d47017ce1fb3434245c8435bfb671884aff8dbb051fb3ccd88c7c402b570be0ef5a9e0c1d768f161cace6904bb9f22ef69f46597495a74cfa250414f02a36bfe04cf981e3fc1aad72150b4fcb53aea0e470d72da60b238d33ddc25ebf0032a78900f9da5c9cad255792c9af7baa28121e2059c06d953faa3fbd58665ed14025217d8c578fd837383f7985ff7f7622b052dc04e2270455fb1f07b32321e7a3e027f1fccc74eb1571ad25b2ce28165dfe028aefddf6be08176eec913c0c3e6f65d02d9f50ed597b5ba907f5ce72987a9aaf0818e493d1223366aa51156368e6cec6703bff347358d523ae90a078e2d17dbb7784c75c124fa48a8883e39fcec240dfe0b03770196cdfd6cdae0593a1c39653a24815c0b33fb064b2de503acb26ad82342f2023d0435b3a6698c440f57ec2ef4623306361a12b00ce09afa2e3720d910aa38fa03a212eb621adcdb5a9b58259d9657462e15a17f3bb346ecbb9abcec5fb2250288030d0237cb80a1a52dd790f01de3204a22c9b897cccc0ea25e9b07bed2e2c062570264fe061f084bcec411d46a788aa15fda8364bba4b3b3f9206c070adbcef86b2702ff6737b0842f54b2f6dddc75a0aa066aa4b7b2edcd88b8d720d532d0300bf39302a8747d29d61205dc407c34bc0f693643c42c13fa7e02198bfae657b67f597f2d03375dbeb607d7be550a4547c7bc253ab6aa46846476da7f91472a9a358031e978038c3542102a8fc4263b00cc5c5f5a68170c98af95f357bca3f875da2f0ffb6d2a02c063531b87d5b703077b4934a65c11c86e4c9db43a2371f2836c38c8f1ca87cb03573e527e24ca47d0978510ce77e0164f04b0db4487e12eb7a01ec79bd7583c5b03a8d4ff43714980aa37b8145e75ec517951148f029db0317e232856b3dc590b7602e55953c6bf2440db4682f191dd98f129d086d14a44fa1abb87445a18b5f6cd770326f3e983aaed4d1d20166a9ac9e0fae57add0e628d3e6b2a2ad78fccf97b15ff03d156caad6a0dab35ff26aebe4a65cfa12692f2d963300a3c60cf4977808aece20271ef2f1e360ed9e0adf0c312d8e7fe045d00cc501dd43a7ff6d3f5b7595ec4b203cf179d13cac3750199982bfcce345950c5a0f04a33eb6c6820232ddb8b0c1e9003057065a9ab50fda61259dbc8a110278a2bbe672db7af47df6e7f22a49857a94203bb3cfada8e89268fb306b7531df753f9c78755a17ae81aecfc01ff937c7dda840324e2828e533a1ea023db7d9fe4e9d548132f3df09a3f53b8c418530d8e59e1d9022284cc281a3d569112a4976f8e559594f23c6d14e55786264a9457f6ca54518e021243cd951a7499b5d3752efbea29b64ac8d5d4f07e7b0d8fa61c685c16efe06f02fdb78144392d728f5d1faa99e7fa31059310893b8a13ce84acdfca3c294b9f790359c869ba54ba0647005d2b48ba2542a4cca404d65661a7558c432f0c1e46867f0214eb5150cc1cbd4a4ff872aea0b8f27de6772a400e1760d5450f0fd33124f54a0300eba3033f9ea04ffc4ce8a0890111dee4b0a55edc67b80d2693f188f4c2fc2402b733ecb5120faa8e9d82f399845ec781ce38b79264b835d8c3cfd6f69f2515f0020e68e2ee4065f6e9cfffafcc3e0d7a2ebde5b48f8ae3b053f2930ac30eabd8ed029f920b79135f85f04eac4896e69e43e90e058602e41134388b1548f43abfed4a037be921bf3908c90cc122ebff3a832144980a7e7e734c009cc2f65085853ba0d50220705dec7413b8e632740c69e7d991b1144f331e1c920351cf4ca1b30193c0bc036158552889ae579b980ce83c87630b069f95e81928b05db1c6f991d4c4a21c3803ede514bc6fca178ff44f783832275bd1d07a9726db7bdee049a61ebfc5c661c80335a094af4ee1e177a1d0f3f57d01435319127e7223e1a598c1befa7c4e2d4f0b0255b3655835212dd96f0f81c0ee6a370405df88151619685d68f5126654a18667028aae72f1e3bd2d88e03f4ea23cfc47960fc0163ba24d3bacceee90c27b1d6fdf0312612b86387d4be12adf46508468fcd21e877b90eff9e7635f76cc32a14db0b602d05b36fbc9e7bc32ef8579de256adfd37b81b246016982daf68a061adee791cf02730c29bc1bff680d9887983053c7d4788def4e85682731f79d56ed38e1087da10265069258861acb63d3113f69a2b308bb0bd97685582efbd0b640752818356cbc03b2cf9e73a622aa5dabe730e3c65989116bacbbb272f3abffc71963b4f921415502d835366554be8ea720a5643a006c4e8021660636e5f5e31bf6de211df4e76297038ebaadeafbd4944cfe8535dcea4542ad2168db4451440d16b918f76998152900034666f9f9612fa73d15c2b5a4622d9faa4ab951a08ef500555ba605d9d10f2644031178eddb8483cb234b3a9304fd910fcede10e063ef740a07f3b3be05bb872ca5026a6732e7937d989a4308fa6e6cad7a9617f7719d72ec4070122f564068e4ad1502bb2b973cb5bb13f39a80dd1df78a48d280ced7ed71e40616ee84b9d5a61ddb2002cb57e61486124ddaaf132866884397b6eca0340b0707c6ba7c5d0e8154daa52503b49afd68352e87f7876078833e3dfbbc1e8464371fb2bb46a2fc08ae935ab3c50274ebc9b2cd36c206fdf0f66151e3f2aaabd5c687168bae5d6b0efe5e2ba64da80206ef7b5af7c5ff22b2bf334e08ec35c74281632b20641d236b1d4406354f9728032d1cab203f91bc606cdca44a622a0d8b1b46457c792625b7c9409d1614bb80b30246d2de13bb7b9b468252e9f9b87c20f3adec6db7b7f93f1b328215e9e18a3f9d0205f65108f85f1da193a7e8fde8dbcbb2081a92f4dcfdab1736cd61305da56e23033c98d2c8071006920a0185bdae02533cb5eb6a211c0860a9cc6fa6624aea6ac8031388542fe2aa96497b9412e3eacec26c51e56d3413ae69a7784f105a392428450247f6a8b32b442d89c737640aeab41fd5dc4b930f283a7eaf732b8892c85eae8502fc49e4641bfa2d9a6ba85460c14e200f22043b2cf382e6c98c8cbcb28ca4e74e03bf6ed4a9cc5cf4d1ccdce88153e09c31b0d4878f61cfda90d1ff4b95ad2e476a032c8227b20c516578ad1b8fab43c3b0b01b26309aab018745cd4b7b28bdbcf93503be88aefb35672f822f4511b23e5c425d1abe467df16bf01ef5d868079aad84400205e64f586ed8aba7cef72f7ce59a1243215e12315aeaed16f5bcec074f258e69030db6b598d31c4ee635ac62576c7882d1318d6ab0a2f85d1735cfad0b13575f47037d5b7933577f3028dbe97d7ffdbadf641ec273f2186bd914e582825a9694b0b203426ff022b184c90dc1594e79b20e684bd1afaf449bbf2395c31e8dacbbdd1cba03a323ea2b61b54139826a80f54925077d3ae501a4525361f4f13597ed31961c4102a60b24c9f16b4b18262a0b2d38517d4a15748c604d51f2a33ae96fe65f9b82ce03993d74f2530a090965e5c38a5069a364b76c202687f23a0f1c2a90d533c4c8960262373e94f12d610808ab2dcb319b101f3cb5827504b44d1d84b9134bcf20b8a40332c34480e65c439d7484d1573502af1e2c07d3a648612ef8f46d65cc909f321703ccc13ac1df98457b5fbf1c201fc61a73a9daeadd8b1816600fc1f4424b07c37e0201dc93e58621af8b1c5c5d19f9f3fb4ee7bd9a0c3a6c81cd0af74f2dc5adf24603782784d36aaa906ff4850b4c34e27dea7f6a8d322cc567a5218e04a51615d301020926926c8969272a6273ceba9071a29d71114e0c37574b831d19e39642b1bb7602bd7c7af6dce682e38f2c5aeea93471fb025390cc95dbb29eae4cdb8d9707d22503c4627390a327034ebbc7fb4138ec663c466be38868738ff4b68525c42d26aff9030a03506290736d368015717ae4fefc30bc0d0d49c2ed2dfc14df53660f6641a302d3ffa45238a0b70f13d93ae30b224de121a58d0e222387682fe83385de713b4f020cebcaa37442ab6ca536eb76b030cbad6802b307f78a3ced45c4716ffe1c9b5a024a26b6e60c4cd938ad675313f45b6ffa89b0e7a5d116fc94a970ea4d2cac529902be2ee6901f93eebd153b3be45d87961a6fc0ae21525897e62d62840c79dee5c9020e45acc2da8cdbfb889bb8963e66460fb380b4228fb8899fe0d97d0463e3bfb3020a4f6e5250be32c029fb3d05f2bb9637cfd669fb4c13cc581c49c214b6580374034f7bd2172ec63a378747a327daf776ce974110b70edd298f2213d59b6ebbafb303ec741a01305d721918e7d7f46840d85896d9e19a533f241757ec663aed0c4b89032918cccf18bdc215caaa88dbfa4202268420628b65a8712cfb3d70b8a0dbf3080259de9e26f64ce3220a5767db3c99aeb2a6a8b74e50716daa5909f21055f9640b02935146c18caba0cd8e869840b141900b22c38b74fa944d6bd1ef292b0a8b126202e6be284c69c0c39a01dde9130bd2f6c1b025e082f1cccaaea2b60e2c6ffd587503012024105035999a812f01221893ed25632d95d42c6e0a96ed87dabd3f5cf3e1026405da660a5247e7ddabe31501bd8a291625ea4df7ec015268f1445503234c1e022fb61664333daca41828e489f4fed04462c05ed0cb4190d01ebb09256fd08e5903ca7ef74b1d440cb44ea2938645059d47b4d0d732f57fca566dd178b6b0cec4ee037c3f48b7bab7d511a95078bd46f981f1a3218a6543bfb75a65c5cd936c588389027eaf120f1a57ecd8dc3915cdc2e736eefba8f1f4d7ce78c46b86aa50672890b9023325e4f5ecd09da0a1f4014f55bdd57b09371576539c4d1b4f0c7fcf57021fc6031f00297018c8a89ca4eedda4e33e367ce1398134a4ad2150e6e136d943320def02787a4dd44783c3a8be3c9b5850dca132427098343616357eb61bb6d6ebe10c2a02ad9ec3d57aafba0bcb19b88d62bbfbfc379d76711b1114f5d1a98cb5b378522503a53d1a2b65936622afef1fea6639b0641ae1e2c5878493be8f615e0274b1763f03e6083609b983a32cf0a96dcefec1a3dbafd64c1d4d2e2be2fb3945c1ac5cc2d402b9a81309b82ed8bbe00eaa422fc4092c1f9924c48876561c8494be16916b5bec037aae6ceab85bb97b9aab671583c806c20064e7579df9285a36042853d869b31f039b829ea9e125fcf093bdebb8a18f9c3a6003e269b0ff3c0d2a952eb0a4c1c4c903d3a85fe07f74a9cc39c0fdf5c6e31af404817b758476bf5ec3e3cc556cfc43460270ce8e16fd83c5b3d80a1260606b1193c56cec25b12709f76debeb92a386ac5e03e88e1fceed055b8355ba31673f3aace4ded32ed693be4d110d8461c68b3248b00254d637feeb2f7a27d6107a4fadf9c82b1171948b8396882fadc2175884928de303b823964ad157f08ad7c583b48c96461af30dcc641f7266638e7fb1134786938903fd974f55111d8e3eb7f0d4d2c66ab3ea583801b15c1f60d9f296d9e5decf847d038a90914fc8582765e2baf913256f16a7a0541f34c39c11b3cc906648af4db91403f32ead8afdf51d78522f0026d7442442a20dbcd1aec7a09ad461ff86fa23ca0f02fc9c07f6ce27f14cecea1733c4d6787386c5af9d94d6cfeda248c41825cca2f303746164e6f3bd03882e3a369e0d2ce3ba39a1df46918d0f543ae53031d09ad8e603e9b0a8aa0e33eaf64808fdffdd1089df3ae7cd703832d13ff3db26212d601a490383ae568223986582e253da1305da09f16b64582594f3e056be8f3186d17f8f6803fef0f13e497834bd1564dadfcc39dcf167dce1cd5f3c6d4270a2fab86200fecb03d129482f79de20fb7ffda2550e91e01ffb4d00343f375ad655cdada0e9767f7502a694bb5a9b17f92a36ff1cbd9f96c13923f1007e4cdbf5da0779966eacfd123002868df8b5d2915eeb4d01b3ae7a792363f77485606a39d57f683b03d3dd1acf4a031af8a26cfcda4501058463978c8e260e36091dd677e6ffcb4d5e4413e69788ec0385641cdb53fc4d9935a3dfa0bbd1d36ddeb1eb0ed307a48880268c1a44fee87b036ce0341fd749419b4ddee1f7f092d2ae48ae629d6c8461e8483b38dab641798c035916509ddfef05238791ccf91a63fd2fbd7a987c764f44fd7502900e3f6b7dc70380fd445bcbc41c7fff2ccb9d93376f375f61dc4fd23cebb2796eb7b8855c49a30283835eb17f79b18829c8992731ba860adc0f458752cd049ed05d88da238e818c03b1cfeadf717f89a14b3381d7af65689a6e3c209e14f3ab3583db9833ae19151003af1436e6f0eb15d87b47506755155c55966e87f704886f55f230863a301f3d9f0342c49bc6773e63eb6a1a603b7cec35cedc4ea0351d2ac56da2c3e52a4fca56490276c18a4fc5d430d95f0135c9091e57fbfc5c15ac452b0143cb7e5b6154e0d04e034abb8c134fe388fbc1ca593e8de37b75a7ad692e207a8ff96a61100f7a32c40f03521bc9b5b419866f884f5c91e7b4a0ed240a5265fc6a14e5d0dd11d9d6e2e37f023d6f02a745d1ccb49191c4425a337dcb787452e3b619084a64a98fa6ebb8878a03eae5c710cdcffc3e2263d9ec54560be782cf76eb85d1c526174f9ca9200d01be0206e5919ab2a5fe9adc912befe719d353ec96354506d170b764a0c086bda0455f03ba62b71d4eded37bc993be0e964462a80e9bc2c1621fd986931aa923ad196df402b0f13f3860d87eeb2241fff7e041a37bdc311fd7243438fe0eea9b0314b58432021b2200837e2153b1a820fe79b394a65785032aefc979fcb219ce11206bd0a1f4025a561e6d187c5d1a048a66307df0e850eac7e759038e8bd76e3128df6cca8149038407e152343e022957f5eb484f465bdb8414db6d0beee0c0d087ddf728d4d36c03c5948ce4a101c89298c3e02bde0f8dce99394f05fa0a873ea3dd7f020393358d03529c81843e39849c21afa51df632e43bd4bbbc5cabc8bc3cb5854a4a418c83ff02ce3fa075d5320ab8e476f6175c30a5d01c6221277efd82cb68cb5ba291850a4f02d42b6c3f7674ed9e4ab1eb180b88021b50ab5f2970df91b3fd0b9a592884d9a903aa4257673fa000161c89bfab3471ce33b3a2ec05f8ad046774bb2adbd1f6136502e7303a2f506e7cf1ceb582883fb2d3307c32b59ba21be39bfe76fcd0c5df422d03c448b14ddd25eb0bd5980b95dc59598d9dcdaed470bf3ec99cbe30f79e02945b02173de044cbaaf708e8883e9b11e74a25d265dc934438c4ef8bd446cc788d8f1a02809592d177f110a99356a2a86a4dbeda44d71b422a6bbff318432af55dc51311037aecb914a3e4fffe22e0785ec7dc6e281f6fff4f86a66574b93056345216058902bee610d368a571ce34bc53083b85446ffd6393adfd6f7ebc32d7890d626e02ab0202e3f98e0434a79f469e4c8c6e6f42b2949bcf08e81077067220a18853e376d903d19b2f566c814b9a8cd68f3ea90de5e7b21f0d0ffecb5465be386c59b4def57f021ad7944910d92507558dff1dd0c8482aa111ba772004fbd9fc230d9986e8ce9303451a12e296bd4106ba4d3d7caaea79c6a0bd1d952c6ba064f1b8f5ff22c6436302edbad068ab085052b6b92c3b5664a24af7abc4b4b005f730a529f7697362c98c02626a81b9ff914b5805468041b0de104ab1504d73282b95189fa7b7b3f1e73ae9039c412694b2b9318858cbb98794d8626d0d75e019298cbe99572bcaa6ce16896b02e861b1c6b20e70c65c34e8c39c5ed6cdf38e655656f4a543929f4af7c9e5ce9d037708f1b8c97b69f154fb902d7ac58cb7f4b967ff41f4dfd154e7637cbab511c0033144507762cd910e315db750208df4f4f5265efe365f5706820cac278840d69603835aff83afa905c93ac9e9fe95e5c5146bf2f2eea3c606051547dd06b1f3611f034bdeb7329a5054f79cc9b84bed6d746859fc7d1a4bc639ef232c7aef0227f81703005e9d287a433d73c3cbff9a26f08d05128e2e06918f72bed37925f3e522355e03e93b7809fbf37b8ea6ca12654ad931e46b211717375a1bde910c9f12f92d3c840386a33ea1d340ad24ee61059ea79b147badf7d1c15f9743897fd2132e3ae09a1b02410a1556f8fa972e0212bef871aa442578fd0a92ca275a76cf8d4bff435f8fa902400919816519d80870cd818c950b272f881df1f8be84c7675d353867b1ef384a02e3512cd951f8742ac75f035e6098d329c368a49c9de4ab0662c39a747741a195026c44d870f0bb18931c48a8cea7e4b7bc3f406059a3b6197ef5f35987dac681c503f42d5ca515bd1378b0b61ffe9e072dfcbc09a10f4e0c3e57d3a8a0e25804599b03c462644567abc4654fce1a4b930ccdea27328598da06f131fc5ad0cfc4666b5203a90a35bb7bd1fcba89fc6f45e88a2603578a251e94c3b150921e04a5d6b7a5c2020be3f5f2649759c7432c4134496aad8a1cecc073e2bc1fa6225dbde1e7b24264026f839d0e2033cd0b05f6af834d8a0dce63d41d000e64e3e2aefbf75038ed9fd20279169a0fbbe5211976f726afd1e0ca5195a53cb0fee0c94de348a87785fc78ef034d5133b39686e9ec24ba841902e99530bf78d8188d0c76620c5500eff82312c102c313cc0c35bc10f2bc376fa7230932213c88797301dfba471824b32ebb825a8c03a2774b60e153f211dee8705f17a7894411767557b726158e3e36dda84fb93b1c03c19ec3b9167fed7cc71734120d2d6e784be76b65cc702f7086b06db47ab1d012035b95ae5b0381b47b06bbad4e21ceb8e397c2fbb417d7ac49b7b7f405866e96b802f12f68d56548fca2e79b505f41896bc3956e1adc881957d7a0741a247937235103fe24f43fc5c1e298c1a682e0cc778271170ff0ea8eb7f4b6ae4a668e96a435b602baf917a1b7d0f0d204a66b80b6a09a369dd33cf7c7bc31bed3fdd9361e109fd90293b3f4c1c2c2aca0755c75a016765ef50b422cd343ceecde0bbe74e5683108eb023fdf1c02d99067653b1e263087bee45875c5818df3d5c52c1ff75361deeb736903c47e48c1f0b4dc768ef7ed3f4b9c461ea02bb08b95eb8c951ac8f4b36fc4c54102b366be2aab7423deb8599a7f39edc6b32e8a1b5264d35e817b206f3468db790f0372f9f9e951e8251b408d055a63d6dcba94f0842086671b567b00f5fbd83929f40213f3e2d1eb900ac8f214379e702059ce265a64962e60aca34b5c2ceb5de4edbb03934a5365afcb7db4995648a2f58ac34ed247fc0fb1a3c318fe712aae5994a4b6031eb91f8041c00c7c52d2086d962c296b1c19b9ec9b983e067961f54c7a56758003bdb26f63085d080c54bb23836b0d380ea1873e12164b0e5af5d6f720c05be73302e9d1c4650007e12f538e0361a2e75fb0aba0c127a525a4d301fc0eeb557764b303a23b437925e435505bafc97444d72c51c4697f0d9c8e3a6366418ac8911d598802523d1584ce7bfc49bf8f7e6943692c490eb2e8d077d85a29762e86f0217f46570351d07f686f8cc8e70ebf7133de8ac31b4fb51588115509c449611b320c2b091a02fe61455a1d5af702be0290b92e0fd38d4cf44748e4146594b179175c9c7dbb200282606d03ebcac9939b854b87e44fdd24427a1dceb8151c9b639ff5067d296c04020862cfed5e1a3d5e54c31eb4a9805e1022aad3afbb1c9d0aac02898193cdf4e003c0b1e916bf7409675c3d7688698cb390690e6a43e32466c7e6cc2c128acf72990388780d2375321b2269fb7b52b374e32cbea7c15d81cf9845c52e62a1c8bea98e022e312723fa7e39401ab8f82c1c2cdd1d129374d4826451c26fd2d7a36430a87503391c09fe7d0e60cb55cd2df9e0f95a11c07bf822443258ca6cd9334538dd388403277215938664230af5a7e8d430a6ee498df5fbf0b4778b4262c56b5a53541a6703471bc91525fc5155df25ba797a2d45c2a662be9d781f2395340f2b98014c5e9a025f970973d2efc398bb09f33d7ae0955bbe4109f81c57c1f1b63b62501b0c9ddd02c24b44d21c5747f1f5fbb5b9413d372bb9e1f938ea22df60423b11874dd6b88b02bddfa968f7e146930b01e76d365056fc0ff80a8c5d3aeaa3cb0547649211eb9a02cc549fa3217b30adf132fb2c041f2f3f1414a45bc1bc0cb2503cc61b5f79bff702b0fa53f2c29a54bbd56d3f9e5e274de78bf9be21538d6b9ea55abaeb4052d91803bef50fbba6acdd5f180be3bd6716287124d32b08962ba7884f0736962e6fc4150321d30a85d4e0badb6373ac4f9c0c9b633cad09c1e4bfcb22d4e75d970a846c9e02bb5a4a162ce320e571bb9f29c896effe3edcae6dad57d5f55275c52609ba9ea903b6057d7f10591058644d5f529fdcb0490ffe07e57a3d1a762ee157c41c5cea880396ccd8b75fd23c117ab840040fe56f82f1beb2e1b9a5385061d0d9367d00c5b60320707076f708405d5be82b5079c61f8bc41bcf3fd7b44c8182453a6d3eed0d69037dc4b88949d444b47052991f7e9b194bac39813173def3ad2d9514090bc09a88036ba99501cc49c7917e4cecf6ffed0b0eedb0edda78151323b5bf205e8cdfaeff03e1ebd9170b6a9026125e48cf9149743d1e4e6b44f6affa5ea10bd3a486d5f202031a741d2686b9ea69b72c3c842268ea08d5ff9afb7414aad0570d45b97b9a964903f04adba169f63b7695230ce2b7bd21f93bc53d9bcae747a8ee8b812f13652ccd0304bfab5ee5beec44bbdb4c199840f3e6177e8b25c2231074435425dc361c16ad03f858f235ddf9e9467fa557ec97de978074b931839379352ce5ab6fbe6ca5444c021be2be1a5fb6c62d8c28d26e808bb24349fe71fd125d9b82fe846fc8f4b79e5c02e83e3c2b6e85397ead7e4c81d1eba14e9bbcc9f10a944b0b85b834f1f776a43d0281fb589dbf6ffc36393f50a80e438e9fe821ea44edf30ba48484088c2768bfea026f3880fb9f5ec04648ac0566a8bfdb8231ac54e12c0e268ccdc1ecbc20e6413a0307ee9a457591cbb211e682325d915f162c92bd4ed6c2cf76c8204b88f2dd1117037fe21acf98f328f20852458f1995337bbc033a84b216c2ade6e7c5fb5b9d8e4c024019cf710a088a7b991cf0640cff9465ec116ac9f78bf5b90d8948111697432c038a5f57bca09079d25ff9a6383ef9e8ae51cb9ff3a558a9b913ed1fae3dd4fb1903b96871075faf2d263b2fe2a05c5074d78059355551fc4dbca1def46d69ab12450326ed215ebd245929400854f6b2a40ea64074a33cb08c2acd6c491f57f8af085d02b783dc8aaf53bbceb73ebec254a5a618bfd1aa8ca4d9ffe482e2524ecbc8c6ff0323f9409971712741af1c3283e828ac73cc9b9d50c2530f03a490dbfc1beca7ee03acd05293b841bb8086176ef789ad4c5202b1d51f7205284e6f2f65bbd7d21a9403872d0a0fe993ca01d7cd0bf73e4bd534810e282334fea932059a3de4fbf53aa702079bd895c9e7a029189bb40a4b081f79bd33e87d077123cf2ace949e8f6489ca02cfb61d2d842dcddf9342db1af1d9f8f013e3d6115b47d891a30f3444275353c502e583a4e469d0e5a633f5c08f1dc0b63322bc72ab5694b6db1cc4694d329dbff0027c105fb031ac9ae1d36dcfbf3fe280e3a963d34f8f99064685c33126a1c59acd033e534157f81d8d54dbd687beebd57ca792dd3ba23ec4dc9647bc6344c0471b7203f2c1e449f3025e324739fbbe34ce040949f30359518e5d9137ce5cf171016a4e02d51ad7529c4b53e09d6f0ee54a1b2e3a56d7904569ef13eab5c113124dfc2d3603f69ca81ee00c04ffb3a5caaad211eecbb2b6146b247b14f666d6ec876b152b7902a686cd0213688e75d389743139bbeb6fac862811e27c983168166455453dac5202d915f458eec1a305ed71e0585991b3cba521759b4643b1a97557cced0db7bf0903db5ce00f2a46f232bf495081ab1a707aab0e2d34ce8599237783d6de9dccadb503028a04ff5decdaf24361b99ca59464c0e9d3c1183cfed08b74fc655713b881140377275dc185a013a43a50a9e45eb55c14467372b165d6aa4895256705c34669d30224928c5fdaed688e33c2a0cb2df814bbce284088410ba19b41a15ae4455aa06d02a53cad1a8a77d168dd3cf09ab7a1bf4396f00ccccd552220b32d7f690fcc89c802ddbdd62b67d813b4a33a44bf17ed8f09f25ffad9e7746d3acf7f7a81168f77e2039b645690e5de62cb90571131e635783b92a44afaecb0aef545a58007b9d0279503d996fa4d836a44cd9eaa1f31ff12b5c64a41765ab130a08be41a971e96ee2e05039cfa519f2c4ffcf077a28a333056120f7808bddaf8e7770438cb363d1349caa803835404a497c01f9ab7ce466968e576c227b30d50f7b4b97b221ca166879a4f9f038987c8402450ad1ab4c316366736660e2570f2740f2b57530191392e5c439ce302721259f7581dd470d16fe8a07f43c0ed7106e085300a2dc92ca74d4fe9ed6245020402756ebeb333a8bf19eb9661f5db825096c0413e135394be41b74e5ae326fe03b78277e3728d00754fd8a066490c8f3f794ea65ab2f6b00fdcff273fcb0c97570286c3f335a57e510177854ac77086313bc1b13fb6a5d715894a18422a463ba15d03ce355163ffef446b11abb7212d3d87d34698bcd1cb256f65f7be70a9751bd2ee02aa6b0df355792141b30f90b7cbc1a79929acce755547c157ea4e116d0f7881b502126869a52418970c91e02cf8a7768cc9d5272c51041bfda62405debd4ad1f9b00297d876e1caac8875fdfe9a0f34ba40ff7ceb3843c2d392246eef385625141e1f02a5a64892d01e02183430bf208b10b3fa231c9c3fb34c394d9686aee691ef2c0802faf0fc6409a094d06b339d2baf96d4edb38061d95ab9134fdc067102c83317cf039ea4ab06ad2cb4b2ff32fcebf9f34ed58faddf5d20c2145440673b1d94c66a5602281f7fcb61550c09c5562e1fa3e8a2283478cd976367a60081b95afd357cda250365880fcdd9d4d5dcd15ef768d43dc40c3e2bbb428f9d8fbd4e37bb337eb8a515033ef996b38bcfad3cdba10ec5a0e22e2fe47749eeecb8f025e2eac84bafd0167e027003c9514637055c318687bb328a70570743220ffebac9f7941e2682716690b6023248473b7a59ed7e8c1cd03b50426164b1ca0c2b8dc20e0c5c75946cc62d3d9b023a575e8ca811fcb0e34a05370facb5e3282cfb6b2d384357d1789ba8e104ee08036796e4eec0122f5694ffec974fa9f5d74275ab5ca17426a72f56aa9965910f9a02716f0f75595367d147aab3cf5e082e744da911161a380c0d7f818faddecd251202fadc83fe2497176cb12f1486f39120844ae56bc35323e976bdd5349011fa04c40234e6865c7671ab299f40fce115b2453792de36c4257e9da42c3195f4029c0bfc0202928657971512498bdbbb7a9bc754853aec66e9643002079f451c64c15afe8902c3147a9d5f42ad939d847aae91a641b2cef421c99b050982660e079a66c5ebaf025e3cd24e1c7c1e0629fc1b1dc5f26951a6346347948d7ed6b8d5feaf49141670033d9dc4dc322aa43bad68cfb5545898405e5ca22121afcffbbf914a46c874139502c85a31b3b6aaa7d2cfc5109e41eb9850df07f59f8b6a320dc0c6ba133d69188f028100b597a2c06a99c02277e1cd7ac09f948ef6387f7268df6b4e17ec36f9d6da0313c232724cbd4c3c86c84b846e0f43594ae289f0f839594483dfff2ef681b75403db4e8b664ed91feb5399c547de170d7f023a147e761bdf2df8798d8ce021de800309d6d33deb71e6af8bddd687ca240d6ed006ef9cea2a0b7ce85b91f9bcab27510290235ff42fbc0b2f3bb4b9c618ee13cab48346e6ebc2c4f7c36f110a7310d01903e33f936d43ffad3c176abc234ee1feb24ffb30d2f8f38d770c9fac7135c9912f03eb2649d76582a11d3b78ccf97a1d8ee426cb0349939ba4b6ebc112138fa1c69503798735ad75e4872ca9598f28a239375aad82067331120c5ad16186772a5a93e00380989cacc0083685ce0ab1e490a76a5eddbe69e26bd040a4e69fe92fba5cc6d903482a74b3cca5164299342f7ead8981bb3a5e09ae3df353babb1c07d19b5eddf7022c3481aec6e38bb7996893eafdb194af2e46236ee2fe24a8c77f510a9c88fba503524f0307059dd49930a3a09991f35b53e9cd1af1ea2fa04fa70ad33ec0a58804023d9d0a5e13fd5ac4896aaa0e8b2e59d164edaf6d96bfabafe429f42c1633291402cb937192b8d9710584b630b788e5c5e6ff4a817672ddff024ab439d07c373eae03bd7e6cd54c1c14312bdfee2d68e49f0118bc5b223c3a7ead4bed8e6371fb1850032da675f4e2b4af0165cb44050d7c0a9c4c6fb02f1d5f31ccfdcf9d9a9c9de629034396b5cab372a305fda0e70ceec504cb4694f533ecfbdf074f26a356441af37502df4d45a12529c16aa63ca613ded17a12e4c0bdda5787be6af7a279175b81abf803d7bfc32e59e28da8a9c993dd52dd4dba443fd1d73b40ac8cbf2d21efbacc675a0288025bbde6f5c724212eaa69fe51f722978e5136b72d46eac773b85381c962db02ba516cb1344d873620081aff665d398009519b10106c7f48897a9c146adb53160395c0f0176625643f3013f9c931df5c4aeb0e493f8c161241a5234b87df9520840267a1bbcc2baedbaeaacb6b1395d081d9c20a20f4c879bdb4d5a65c638cc3530403894806ecc2b5b56d3d4ee2b8462b92662e5ca5483f6cedd07d7914acc9963587021bbf9f1ba7f3ed71cbb2a36ebe755b42fdd1b9588e7e617e9a165645ff2ac1220244d44f43310d9b842a7010010aff331bff6c005fc48b7ea91ffefb15028e2fae034e5ea89c839ebddf41fbe6d4cf8e73176701a69c4d6f74f47a0ee5de9fd33ef90348d7603ba4f9a60b3c3e2cf318f0908abbc5e09008c40b9a6328b21cf557bc6402d29d86e240dfc9de8f198e6078e9d77596d69a1d70ce8f2cabfa81a7bcce8a180256e846036d595d2a7c1e2f54ad53cd316e9691847a0b918b93479f9207e135b403a90a821c2352fa92c19ea58e61a2c26efcd8f8c7292e0a02cd6467e34ee3e2c1026702d8c5dc4896c6cfd2c948b23d521faa18250dea9d9a1ffc3192717027b580031a0007449698903bc47ba5d6a8d051d304f21142c20beae980b5f7e6ff9a2df103fd97c387a4e85e8e0ce5550cc780d1977947400257d8fca800ef91a03f2e164f03a17c4a2ad3aaa4c45a40874737a4911a7e102e6d9e10a768f208ba57829761dc0276fa712984d8a34686650d155ed8e8846f83d731ab2c0c0ce09f786fe429ea6c032e3973a625b1cc9f929debea3549cb116cade102c67b1bc08d6df48db417707403d83a76ed6f92166d2cf5899c899bc9efa72cc37650b1259dc299bf49d86d29f602c2ae3157847d31d9aaa49d0c611c82c19ee403f9ed818c9d88098374e93460710241b4d12c300898914224b8b5e764652519b7db43c124b10e123a787c1633420103cdb29c6c39eb954a4a33a8102bbac2b89ce65a977ed30b9e68510c86a609d1ad02999213df57dc0c1d66f79b3d58e01ccf4a0111e36a8642f5198c39b1b4006f0a02e8f5247844e1ef527ec28a240aaea896369fa8ea81401617da42a373ccefb67c03af2f2b53ba903b1dda66611385147aef62a852eb004fd05404be2ec64414172a03979dd428d12c977fe3c231ed8e488420f6f4b562d630c0d5f4b02e19d8f70e7b029b088d4ba3577d6037c7fce313521c8e79f5c0e247f5b18647f151674c84cb0f03273c5723fa4f96cbd1de9f87ee6b85c82b01ea3cf771c63813e480ea31ea978a03d44cd87c889759e0007ea35ad23e805b329adb84a933729e4d1da676182a7a5602881a36f205222fbac8e981cba75225318daa84fcf01e44863d25134c38d00098030def1be2c5aa5644cfc751cdf85ba28b41b59802179fb5771b2d84625cf3429c02e90fad11802f8469ff02bd31ac92fa36e764f0f60502cd237c52701b93f1832103e02d820de4362bc7fe948d0b43fc2cec6d36f4d3311956497b13186c345a797b021b6de183a978f03442031ec3aaea4ee6c15899a9343505e96bf4ae82242a93170373293b3ddd4ff6e29f77bc5956f22838a510aae1c0ccbb8eada17ce79eb7502803f2b9aa75cd0f0cc972a73c099375f42fa9ad24fd0c729632754ccefd570c585403673fdfa2d19259ab0277b7ed4b4f2317b1560911819e4b5b8652921d452c5f4103fbeb0d2875c5c50b68936de9cda4d8a25f9e2ab08c36c1e4a0f8791f0917214202fd4321ecbef786830a3c281036c73e63469057d00e30d49684f7b9bca8871e4502b2d995c17f7e103393934058485c774f9826e7e0f1de2ff5ce207213516652600332800fa015ce0cc0a2834ea79296c8f98d4cbdf5388422d15ef45678507ac5500306c950c254ae054a6341c0ae1a67ae7d34f93fac285ef8f223060a53811459f403ae0f4f3e17ddb448f05e077b51990253aafc1f60a6d459d8c55b37380f1e8adf0223578472c64da8e094f10e6bd91043341655171ce55a56045578e0bc0b858723032effc30553a65343b9eb27fc4263c3162f2a9c579eb7ad4789978d2ddcc64fd0031aa5b56644804133203f5557098bdd4a86779383a3ebc512c9063d44f29d96e402dcac6ad87351089f776d6c7bf0575ecaa7df8b9a501ea9e50ef883d75060a8cb02d8299bd764694f8061bb86c1b85343a5f6da66d426522c687d90d43dd18d858602517e133f119e04ff10ad0b170fccc65967ee4b64a01298bc877b87571d12d096036996fad7fa7c54ef82638fa117f818a95adea93226df5e2519d4a213973bdfba0360cf820d5e866f59b8786f92ce6bd103af6668f3714de846efbdb2d5a7fd26ee024ee012f5e982181f15cf6f26a89d8afeef975e1cd81a17f7768f3953abb252f8038289aea87f98c1ab7680ffcf75aed4902943fe713dc0ca2a5d120aa54826b579024a9fa56a553f739a7d5d1e7450c379d21b643e15f3a7631a4a7ab64e90d8e44a032ca9f26b7bf346cad1f1f737d04891a8acee2ff4a72e96f556f09bfe198ae9b603bf99d86c3c3a220ca413a018b4017f2b1fb65195da0769c329dacc9a81c8fc690312c75a73743e6674afb128a837b6dffb559db5018df2f2c744a11868a954777002de8188116baa78f9c203c6b7daec9f0bb371de1c423080780cac520ac4e5989c0399a054843917819f25cfaa68083e17b33125a6211e4a591cb83d9bcc64fbae07030dd8f2a96c7d3ff8dfe8f6ea6f663e7949cebcf12bb1a82aaf8cebc28ff0c7e702d9922f48ee76351e533aa4e567a92b46d5b3ead9fb281a3d3f93872d94f0e8a002543369a52fe18753bc85afb8bd04226c46086403300af96f11da692a9930b86302a9351b06a5a72940e5e082cc7143360ff6fd10e3e8e654fc2ba4e04f4f948fe602ae8ec7856ac02552c5c2a1a1eeade1a750cf0cca9aebd03387a912df19dac4ec023c33965be5354edeb9f3bf4bae7b240fcb0fbffa0ca65a5d566fc2bfb4b5227e0355a712fdb45787a7693664bbb7a309bf0d073911e82429671be74af5990bd3080321e23751cede627eafa200549bf8643c2d08c75dbf691b44315c16f831a5e9560282c7f9ec700bebd01c1ef4da40d60244222c45ca92db7fcbdc7bbd876ad3ec78030f6ef6e747e3eb1aaf071ca906bbb0b7b6e5fdeef58902783fb204f629c3f21403ba1e7395c5c879e3758f9080e7f5addf6eb42cfbc7f084a7d165af424de1378c021eee1dda33b1593b1f1d732254384555325825dfb0bd3636b10609fe5322dcc2026f1f8af0344206f58e09bddc2a900da4421b4559f72d669123e8d07ac598690502a70dc12db422cae537221efb59816ea204026e1d56f07899f3cfcde905f9bb3f03849cc91f30f26ca551e92b53bc3f016c59aabd596d943ec4b22313b3983b0363023792dbefcdb4bca5c6f91d07eb0da27fd5e9befe3824797e6abbe93110fe6763029357668124e7d1ca6e2d9a5e5245a6d956be83c59b686ee7d53814c1d3141f99029af7d1f3565bc2fb99f13683b66f2d021773adbddc5243b4dc2a1159945bc2e503500a55fbe845d5027f36e582fed65a905d5e07137c9d0908260594149f4e0e1c0247cafa45567bfa6ddb0ab91abef29cc8900a7d0db7170e329cb0016602f5224202a91ee890948294b0fb5ad334020a83f614f30bf9be735fdb3882748ef085c381022b66a1e7d50bd691211217fe154fd9d00d9f8da31fdbd3040a0c38411deb6db8021642eee77a1c80f7e6cf43e2f3cdcbb3b7872f6ea8e201fde06a5712d78e3b730280a9f1688d5b9b1f21578767a78732ea4ec567130e8fbb83342e718c88771f4702101e169128db4c4525a723c7627784a58e769ced9d80fa9dc352d7a2fe63dc9e029a8e972b3ac9cb10dda35d8dc442206e7ab46647c669acc948fdd11961f9b04f02a26b67eb00f94bbb5799f8f9907279f6dd282fd0f99026244a50d6672fb8652b03d49b139bab93789c3a298d3623c335630c791407577324819b3c6f808ec2c20e038310301ef0c02b24b834ddb86042de498871403fbb8236f749393811f01e92f302efa10326a097e9653a933923e2c7b1964f1f5fc901b41aa1c8a11ff73cc05d4302a54c80e7d63cbe3018ae309fc4931886e615ffaef104bb29f3fc758ecdb7d89f024c6798679f3497f242bb417482345745381710c1add3af84b3f07db66c137bc40301a94c8804e618462cae28ae1d9d31fb190cab4ecca02af7c3ff7f5856759c0603bb95a43157412f2f9edb0f0c0817b553459acb4b797b6fc549248499a6043ade034e1a0956be06866ce6d4dd9f001ce1c9697f180d94c781630f9704b930e52897034f18b3cbddfb854c77f41ec3b9e1be7f40231effd8e681a55e3549aaa065e93902befaf1cbce45b007d9eb6346e407aade9c4ddba57eab8afe5f017c15831f09180395d26e21786e112c55afce9144ef5c335e44acc90e56417ee1f7f5491c0026b10322e49d5af7869005fdf6586c24648d68fdf63b57b6dac929ab6ec49d9680916d02fe0894daa2b98e04c3ff0cbc216636668233f20e88ebc045f5a3f2441b294037024dbdd471e810b8f1edc16d13b99e71abbc745a45215c1315580740e40ff01c5a02400f9664af575c1940bc4eed361d66ae23f7b7d7db43547dc54d5617925efb0502833d4e2bbf6df7b4bc4c0a3ee3c69ef8ac20c676ce2e43616f0991cff83a31b7035e336ebdbcf5328049ed60791a687935d99141896e9197105f76b24b8c46f0e2028af11b4aa74d0869b8e9830e0b0c370851706b8bfc5918f52b420d7d41866939039a03c3670202a571bcfa149cee4d2d2d0803c19cce9da1f194fc5ff381a3f2a902592b9e86770ddde97ab5750a3dcd39567694389ace7a0773934ea6dca357254c0310095a94144a59c20b2708083ecf74e40c8b7015eb936c30d865be0a15171bee02b427fe0aa73381b92aabac981648cfba42ff5c5b5df4a5fa92464d4ef3b7d79b03aa030c7a6a8b87166d8a30b74549be932d6cda527172520cbe33eaae58e404140356569214c4497a94a20bd3dae82f36f29a3baef8a0bb5627a348d42b13a07b83021cc58cdc252d5b21e5c0695086b9ad4768bf34e9ff2cbd93db4332e69aabc7f802f7dd285f4fcb3cef6812cf86fbd89b132a357f311531f1668c971006a91dcc9c02b4138a6cb44062bae64877e4551d017eeff7d67cd6e455775c2b55e422e8197803c9d9b39ea777541087529a9d723a42c4b0b85e9270324a568bf0d119b2461074027b47c7bbfdc8e2d00fac358b719d7fe285424f8f2683516dc4c12efe57fd51ef036d99b4e86c044746b8af229ce1f3f3a05b93a5baea2de2a256572c4dfebc47ac03eef3e5a87db25995fbe26f6cce7ae1a1afe2eb24bd83e07fd5915027ce1b524202483bb94d6baf8549b5ed0d46617fe23f7b291b68351713affd5ec93378f14c9b035db4e00c41fb97149675f991eedf9b2916f9cc8c4bd49331ffa96b73b322953d02a2b4c8cbaa1a4b75aac59c610a03ef06f5b2f0ea0ce5ffa0f598f1044a93cc54020671ef4d5f9fff2381129a7b4303a2f6df84163d0758517213ad4a6a7bc11ce30290cdabaec3dc73b6c477b0cbd83fbd29c60dd0837e9faaaecfc46a45a4bfd6b802e86d4b7c501ffa15ef70f795685e08b169981ec7487e5e49ccd1f3132465d54703bb051fdfc39f958b171bcc80a8c9c6556ba39d6c3b636af56c3940092867406503c2e6864590924835fc4b339d7844f2a68e85d08c768d2589437a84bc9cb60d17039931d1aef2abb9dca650feddd9503e05b7dfef019fd74443d3892bdf4eca76930284917c80e9d650b2efa3f71b6fbf20e15e162deda7a14c52c98603f4cc7346c80259ca095192661a9aa0b186ea737a3b2342243c54e40f330d9a11f5e5669f4328035476865db2b105202af5a296c070fa44c36e73ea6a455d8f1d03819d8cc8ead0032b4a72f0279bdd9225e860f0a513d23f6b84681d33d30c0713f10b99c7d2221b024390546bd3cb5ef1b1071165ab89fe65280ec1aa11f86376349ea524d9ffd15d03b2648d48de4e1b857bf318e7d9b2296431b015469af38deded761e743fb53e4d0252ed69b0213906b09052acdab3af4139881e3f2407950e51e26a0a85848a7d96025bc5ff35ae7188fde665fce204911e03ae0c6edf913bcc2efb08de61cbc735c2026e44edc8d3cee6d44f4a1805f82a42f1e420e01987e8e53a3c9b96f062945d2a035174fdff4162f0cbde12203dc00c305df4d2a09c9db0a17a2c2e9761d40b44fa0350a924b34cf1b7cc902df2fd421c76c5377f2a1a69bae82b2f67b332d99e706f02bd4a44e225423cc050cfa6ea45226011450851ad42dbb02234e83e0128781091030f459ef055c27e696c408fd7831bc6e21f68baa07f1cdd0e8b09a1db4b535dd40207a86bd4e5c2fb2964d77ae62a486d5f4864b3d4d9620dadb8ad91b2f4e20b4d03f8b77c9b620d920cc699b500340d881d31c08a6f051a291c6dd4ea152ae359ce025cd0cfbb6fa18b5c5a93c80f1517ad57f1cb20b30b5839132ab4f05d242c3933022180c880e0ce96ffef4ea04e17428fd4a9e1739c85de069d490f67fd795872960216695477b2a78a30d291322c68d5d768ffc83853dfcde76c8d7480bfbc0120ee026f63745a1fa2f3a809b31e0d8dff477838ce6a260721a4cf22138d6f98467bc902c61f46e43bae9da042e8d67216a3ef689b71f2b22cbdcb123945add68489fa8a030a00a0ee9e8119a49d177a5cd5d6ad044006b965f75e67cf2f4991704d281c6702809acb02b6e3c6874ff590628e33b1520dd0aa676d373dcb45933ea5da9bf67c02285e92e92eac6c6a8b168062cf28b08ce5ee8c3919d623ba7e73f935a8228dea02b682a92f37d646216846fa18a9d41474aaf1a56df165ec4dca50d4c08da50d730222cf572e8bfffa8c528bda3167a3c20e3ab76baad26dd16acfe112adaf00fe3b02745ced19ad49d2286ae4900f88d9f8b017f0b6a90f92e06bd22ad60ccb16a9ef03ff2755b567ba8237b1c5bedac7887ce929e7a7c3ba30f2f54349b1d972bdc20b0371ae05e5c88346ae7f4b11a226d94719e96ae07f6644b18815a349635658bce102f95224856715876487055c66158663b84570cdcdf4f402fd78011210c50c726d0358d7107f2b80b84f0e78096ec7dc5e569d93cdf0cc5d7ab6718d4e7d4f045de703972afc963d0ee1db2a90011723a96c548d86a82cf74e789c97c18f3b38021f830235cdb4306da944f1b5fc92fc81438b5bd13a0400f6d83ea8b43ff00ca25562810359d3df4f7a992daef52f730f25b06f349d81014dae44df6deeedd5ff159349470386e4ce11232139d11a3f5274aeb6848fdfb597f97be339a085e5bddaa18e4169029e71d8c41584632218156479b5c6b608a75a5ef48f30eeaef3449ce9d69abaab03af266266fa5d0b9f09be5db6c2beeaf879ae07a08554bf542f3b2dd30b25e4c20205c5914ae64ef8a58984f9b4423e5fb9e6487529e4813c7e97a22d9a879c281c02e1ce8a36d45eb819721e546debd6d4ee0551b1573c02006099abf624bda3721703b1011aa5abd9e46fe03e1d46e182500a1cd94ae15832d498a4c5e8dcea8a030c03e2437bb2d8d467ba9f5ddc4455d799804c681b6b3b673e44633633694547baa9024712fbc410c4df1b8f090565d5cfa963656ef7b28136b6a5d733de4f89a0e25f037cbefc311f1244d41e6fbcab63e9cee8475c43da9a3b145fed5cae0e93c7d84c0264e5a6878f7c90814fdbe5e45503274d980ec5bb9d988e44e33fba6cd112c554029a8452036f7b1f825de15b02c3167f98fb32a0be0b17b404fd6d1ecaffa2b4f2033807fb57bbe68ac5d45c04e886b6cd51648206b40fa7c9f21eb326f40aaca7ab030b2735b75525c02ab00ba7baba905253d990189eaf718f0c879fffb5ed9401c402b2c70013ff0613b23b5d2fb448c070dca79f6d0e65ba8649a9f843758d0c974603a5b077cec168d5502654c94cd2ba0349a6f6c7dcf1f9604012193ddcefe7622f028b9bf379158278b7d5ee894efe73690a9f4874d915b1b0238e9e54452529a84a0272d3f6eefa0fba1e4741fb3bcf04e65f79888875534ed387a1d67cdfa5f232960322b00ce9b8a8a4fd832c62d031c878ed983139a9064dc6a33efc1feff8a1105f029cd39d6a65ec954ddaf9ada02da8ce40b154f57f85349fd2fbfd080a63a32b98037fe6e7720f5495a385a6c0910f312bb52706f271ccc296df63cd79637ba0d2a703fdb23b41b0930d637509dcc30d36590f68ac524512084672b8f03e19c66c79cc0343c762c2e84e902b9738bf098545e9201e3db61a63f08eccb2de58e5fec90a3202d490420e177e15bddbc2e3b2105559a48d87423b2f684c02867b00ee793038c40378405cf7c081ac0fe9941d62fe287c7e44442c9583e64fd87fac38d64de5fa7602a1d070958ac8b483269c57e804698bacbb47c7bf8354b3175b5dced725c1917802c7c3f02da12d6eca6349534f7fea4d4e07654c305f362ca95bdf61b91caad3f903c8c5b882d4bca5fcf5c83bb79be789d61a6402ea2a790eba4c559a522e443bcc030ccf26c64371351a959058dde54af08f8d8766738f4dae30f0146368eb2004f80380d2a26359dda809a4a9bcdcbe9c0416084e8695197595a62832e10b1bca57c803de831e448172c871415a30cf45d04ab3dae34d55d1de012fae272ba44165910f0359c00f597e3ddc5a35366aa3289eb8295d81a636547a23ce523d53aeb56204e8031e32fbe0b70cea615177c496cdd5fe9fec340f295f4a2732141c337c4ce21dd3039526cc8f3e165a2edd092dd2d3e9723867e7bba43991697ae9e2de9b9292960f03d04b751403a553bf2fada61f36ce211d8446d9019e1d860d0278179046841a860255b89f7b47546c0fe07a4955c993e413c7177f99492c04867f1a48d7eef5b958024e6eb19eb7b51cbb2fd945e30391ffe37b4d69d73a980843e71c9e75b4f793ee03dae5eeaf8b9064e968b04889f987517526facf81f962679f16d97f37fcd2d30503a5a28f97a6525996fe456d31e569071f47411259a36f872793bcda896490e108038952357d3ede06902baae68ecb5a9d7e30805c393657b6767d9611820b48311502456b77d646a69d896f2283931952c4e66de556bd81ef8e73d3e03593e6768a540207a2f05e6b2ca693a3836c9fe5389a235e7d8d5cf5884e07f4a3fd0c1992f8460365270da8f6455e2a2e3b23304a2ffb816914eaa24f38609a1e2b270dade3cb5c038944c1d38640be3d071dd987d4958fb3abb4afc249b26d6ff723cd38fc02f5570394531f12051d183bd53190a8409da6f9880fe12cb5157f948a0da9959db90a4c03e55074c7b1f6a48055e5b4c70bf0cc1b84bb2ddee6e974c51b98400f9012e39d020acbe43353275cab230da655bf096c97c2b28e14e52321049d1f815ee3ab382902372187bd77c08b391fd7eeefebcddefe991311453e80f54b4e653f982bf9abf3025618c7c3dde3e3bdee380d3431a8429b10b281dff0525ca2f7c20d3ed4d6cf940265f462f8d1246b396db8755c67c603cd821ac9e4c6791135adc225262dd3c0c203e0841921a4cda93d80e217d45b969cc40e0192c783d0ff9c87479458079f4bde0309ca4f150b3f3c49e4fa79dfc0cffb2acfabbdd9f90cb29c2394af78862fd6d803e6da04265492a859aa2629b798760b92492a2ce22bac2e3436ae3f37e3ded0350359cfbc857d2ac657d9bd40b05d43958889803019068bc84ae3272806d69dd459027457a93a3a5d4ecac47a5f1d40ab2897120c4ca11ff36b6610d6e52d6e9c2d9c033b6a0ea19a2dd3adb8d995027142ca1cc0a13a75b8d6f0ae8c6e45def38df07002bcc6eb5e63cadac46016c3951692c9e014c334c7998b6c33cb10485ea73d46c9033e0aedafd95cb3be7dd3e9b9777bd63fe2c8e33ef5ef1566b370bfbdeeef450c037a6c479d47077fc9487869775031a947d647d46cb1d020e0957352cc8a8c8796025e164aa7463f5509b86029b5422b1fefb2a1fc5a87a4d1fc00ed1ecacb90b82b02670dc0ce7767acad06b675605ccc0e9e4f0aac821f9f5d62f78d05addf9763ca02b283cc96f663ce3d4fa0249c0500250b5327cc244197d08475062d06a6c594bc024601bd697f847f12983e7678b6d3c5e3f43c468817b19ccd6c8479baab38ac83020fc5161e07f583b6463d95ef1816acfc7e5119b4e277fd3bfa2ba9e6a8abd289037c2408d8036d90d60714dac0fb496aa41e549ade39703a00b03eba82af4c38bb038bea2482471263e57dd1c3920bb1c4d58730923de4c9c6d250b6e82d0362df1903adcda9fa69807915067d946aad30573dafb7bf2c29ec1c95829889518c860e0803d917713d98369d3c4cd4be203dbda993e89c56223c26a18ba69de5e7dc3491290331d9b0d2b8ddb130a3f3c3fc274b0f8eb6aae507a318df0cc5c5d4d9d2c903ec03af93b3ce4345d1bcf28c656ad8a5787a2c904514e650ba2e5abae45889e5e89602556d776f8c1ef5c0209730bdc8476d4d76ca09b70b0f22fc8484097ab3d043c603df20253ff5810c57c30bf57eb9683c4dbb68267fc4c146ab2df0f1f287f86209021c4120307f49a7040a8d97e628cb64ee41506054ad8cc63fea01bafd0c4829eb0282e6188190eefece16bb6e6c8439d9fd02e41fc284c84b3f80e42af3bb4d867b036fc7b3b99494dc881599cfe5ca3083d4f12968effe57c367a5ea78feec8e00bc0365e1b05fbb52d1fcdfcb0b8969b61d9d80aeb16ca1de8b0cd4255590628be45b029536322c4b5917c8a88a2f00ab0f5054d6cda8eb66a69737dba3c96896bf20a203ded8223e891e2291d576d7267224fe3ad4a9b15a20a7746c24f37a0cb73450020222151fe01db834de57a813831e35205930a97e99acd540c9271a43ceccf7181603e015861c991e47401030acc69c5393662c06b57df8066ea5990cc7a29a1633770303bc1cff20eaefa3d8af717e7d5fca93d965a2891f5b5b9ed5e874efa9612c7f02c6cc5fc58ab9157174d826fce95ad4539980135238d39a1c3bae749aff44596d0302f44e34d6739e0e52873456aaa45906159db36c8497a9012df4759e9a1a26e5031f4a15fb432b44ed3cb34bcf76677d45dd9d0ec10df6eced23f3783ae3334f1c03098b32a72aa1d4d217566f5188ecdb457043c6c3977b809a724cd061cb5cbf4b0370be8331462d71b843079717d9680de046a5a0140767bdce9505d494b31229df03ffa92b25c48b40ee2bd5d408f6997ac6254a72c87c3c256c1dcd1373ec856d1a02caf333e4dd7ac3d8305c08bdd2a1c23ee7572d3c950724ed48f1477bcc166b4e02d61e1b5d05d7a1c06a203906e3bb5cb536c380f50a47cb3379774ac4b962a1910218c9177ce747fa64034d94fea0450f558cf1bda306be2f65df09b7dbab11a55302fd7c83a616e2f75b51f556448cc75207dad611f4da8b71a56a9ee12bdf8b2926020eb1d41e23e2069536904e152224a7945ee23afc2ad3c92c856e942179360fdc02621d17a8099c239b86fc916084662202c533910d98ff4d8ab331c7f40c6736a3026f6f010235fb96da346f4edbe6af5b89b58a47d9c9bbae8fa4936613433ee615032766fc9a826b31b6583c77ce81a36b7218be8705c0fe9bd398d82f1e1ba0f09702dbdfb318675468506a82fdb68744fe39efe610cbdd3efa5d6ec86acd159896ce0391d8ba85999b4a7c2ba3fa36525a462093c31db632ca3cde060c23df96ad143d02037cd0b9675e0f6af54dee67bf4c3c3a17c1f08a5cac9648aeed41fed9d863df03de0a2434abe8c67c9cced7376ea6f04ca6607e82c6224a30775dbc7f09850b6a02003b1b3cf30d06a7887dca1faac89e673a77549e83ccc1bc6a886850467ee0620393cf97e76e8b7dc414c3b0a64f8df16820483f5c1d339388c87b9ed4ecbc379f02e2a472e5c24d75b7c3c7877ec8d2770864718d18979a9a1afa8d1b0622be7a8603ce6687f45996ed3d7550ad19ee6a6821e05548871a7f67e275a68821f89bd32b023014403e8df34d8314a9b1afcb76bff340f6765a552bb2422ebe6ff4ef38682f0370ee63d956a8c5ea74ddc15d46d786d2fadd69f2a48b484dc7142eff0d0db51102a0c76c34cff8f1592c34a51fcdcfbb029ae629c67659d8cc55e7a41357a0172a027baf7cef842c4b21b95b688862ec89b07a1a1aae5b4e5550634698da96c7b5080399635ea9c2cd0e7841d2c1dda700ff8fc7e441652682aac2d3d283c263bbdfd21d0f00000000000004424545468403b20c657667364d04955b44665b084396e101644c1d2bc461f9152de48d6179480446524e4b1e71020001a10f3ad35fbaea167d6800fc3ae9130cb19b98cc5dbeccab99c030672e115cd6861d01000000000000002e8e2979a0dda456cf8e95919b0a1af7ec7d51c53db6e77b08e46a76a53dbc060100000000000000181a9b8aad2bfcb8175119311cb9300ab8dc86bd1895b2e20308ca41de79de990100000000000000f483ed26d723b504f0d04d431860edb00ad34f56b5b44c102bf6f1d33491465d01000000000000004f46828958a41ced9f967c6d8bb34d08b765297c7993f996a504e3c15d0f893c010000000000000088b9a23068a05b8123738df037db214aec18b36aea8e6e02e0e15e68bc2b951001000000000000005bb3a5dd8ecbfee79f17884b0faf1aa0dc2f81478feca0ef97d5e6d0fff03f4701000000000000002f0bf5aedaebcbb1b6c4015687ed6c2e0233b637377a55058eb8f36633329a5e01000000000000002c14a9a2e3a4a9fbf6fa8cc08538d97c4bc76d075eb35b87f0e39da1d5eeffad01000000000000009eaef366be9de2e77c7a468e9eea66d3528c291214d0ff74927b59b789544a8301000000000000001fbb2ccdbcd338e30aaeca6961f9ea0dd5ca02608bf0920a92cb2725d6ca76260100000000000000fda661ac925c3c3f3ab069955a8bcb268c9b1393b1d646af1afe54fddf8c4489010000000000000027bef23159f1e655cb5f339aaa7283414fdf015f7e81ffd63d81999e7350983901000000000000000b4974ab2edb5e350d9661f9ada9e08e3538e63d4c5172e707c6d5791679fdbf0100000000000000654e3dadb4e4129bd1d62ec9d05e405df68a5d370acbcbc10eb69044971802e40100000000000000894b78a3c589ace242556fed1db04a0ab3db97981e3eabc3d7c391b54c510d5901000000000000001c8fb9e8fd991d4cadd5d95ccd619f53d9af0438e7d1fd55ec1861eac9491571010000000000000066ff0b08888644f79471b6a9d03fd4ec20e7a4d39cb4e7b2dbb12b0a01437d4d01000000000000004bdc9b51cc820e38a28f74647f1a9a588440ab696f95850ff448a661d99ed77b01000000000000000a1d7a7710c89165ffeead5f4fda446853cdf8196db6b933dc78b366d58cf08e0100000000000000879dccdcbda14948dc4b7fbe9bc0a9f7e5153f4668bdf895b45cb4d093be0a840100000000000000fb7c302a626e5eb2d87c0b78bbf82ecd4042d380870d409fb9e88f343e36c47f0100000000000000d2974ecd4fcb7bf3195db2f958153f2213376d90a6c1428ff34dbca2b2c9d433010000000000000078171aec62686532427532b073b74c42a901c2d4a8494f3a79851df066561f3d010000000000000097d8ef838b1b9ac6122d809ade1e88e22b387c8e135432c8bcd9494c08b0c3ed0100000000000000ca4e827e9d2cf5f7e9661081a30ecb407483a493e2472e82b0ccf81d3562f6a10100000000000000f3401a1b94ca15af9f54a8f463bb230abbf233e3b299febf6a671e5ba7d9fca301000000000000003b41a12c29c9cc8caa24c4e97930d4be11b2eff2cf2026358abddac4a2f0683a01000000000000008b3d6aaac2230c1ba9ee6d90f6a80ff6ab571f739919504d6e00b684b00fa1ac01000000000000000f6563cb6b5845291d7e5d9b5770d102358fc787f205b3fe7f98c981802e8669010000000000000051607f15cb3d81d5a29de085de1d3601f1626c32ab0ea80e1c71e4c24be652210100000000000000b70061d6240d47c5dd0b5647c52586b1798ae5dd1bb685777004ca00d3bda988010000000000000071924fbde1cc2851cb6fc14a0b041731f970c87506f02e20bf50654aa11babfe0100000000000000337150e2083bf5006768d0a2c4b630bd35a926e09fb2a46c71f95f7ce09a20cf0100000000000000cf4ccb1561317ed8a34efacb46c31e5fd56e47abe48f4a484f8ecb3a300c29bc0100000000000000269a6bbb87326b1db67feeaafb825a7765db09a88833f8ee8aca7039e9a1729d0100000000000000cb16bb84d5780cb3b4596fe894182e121a51832917a62a19280418fbc952bf6d010000000000000007564519bb45371a525ce2635d5b71a288495b265c1f3f42d61df24f37b84cf50100000000000000a67c819f2b2e945a0fb9c9918b06376bc4660f847a9076f14bb633d2456c182101000000000000004880b00f838a0118119f441521cf563175b7dc00b869407200373fedd0e4bfee0100000000000000c30606c5620c4ce9d7ee3b7970bb873de080075b8c0db7f4ba2f1329c999a68001000000000000009be1a2211a26b3eab90bde631a930656a368aa3a3b766e1b09e18236a132aedd01000000000000006b43a02510ac3f1bd8bdf2c56cbed01200a510a8d55e3af4b71cfb74c54f04f801000000000000007d17f470305eb947144b551fc0a28ae01281317bdfcf04da05a52d08b1aa72c20100000000000000cf310b9b5c679d8447f475793a59385471362638cf20328840220342a8252f510100000000000000ed13a03bf1fc232876f51130f871462dd01525d10cff464c9573ed9d0ea561f401000000000000003b8328a5b8cfa9ae5082cc23d74ea7b444526e0b42f90f73befcddda25dc7c270100000000000000013de888876738c853a3fa805ce64ece67cbbcd3bb3692365ba255196d79fb6e0100000000000000410b62f320186e5aefe6aa118b853bfb98d99dec4f048e3e1f2a3b1508450d470100000000000000113214268ebda7f7c30165ca07a77eecca0636fb5df2eb3a41f70f0eb692dca20100000000000000e177fd9892bbff2c14865ef02ccd8c98d987f13ee46e898f3b61c88ddb73a1970100000000000000a001d94e3f344cc8ea4e2d933a4d54f14603bd80e69876cc0496dce54d2c8e59010000000000000097a88d3d2ed0d08d4d4c4b5759c3c466757a0dedd3a0bbe93f3d5253683bded201000000000000003648623e85a66aecfb2ea873e491386ffd66808eccd41bb4f16e75cf3e9a61b4010000000000000020e5a7ec177b970c3a5b66a3a62593d4b94fbd2d49fbd755bd91ad3d1044e8370100000000000000e9ab700c5cbc186c5f0fb3a70a26ba7300bc37cb129e5da9f6ed583e7643efa70100000000000000894ad5390193c100dd46db85f801622509196b381d0975fa866104caf94f9d500100000000000000fbe3fc65319894d61aa304729230714bbbd58e2e04d4eb20fbc37d30c8d2c1c00100000000000000a934964db877a565bf8dbb1a8f7cf19cea6db3f972efa66dfa6347cf21e7098501000000000000007ba70ebabc3f558284dd558521d25727e19cd444f9a214b22153b833b134536a0100000000000000404ed01dc25f2ba0e1ae81787da5c940bd576e8a936dccc7e7bc6aab637e13b401000000000000007b3f1d8664f5c3aa035858c9a7ce061f76f5841aebfa213dc619830339a91a3701000000000000003774f558f7d34475f4eac8bdf7994ce5f92f4e5e9daefcf123dca251a34fdb3c010000000000000080db5f2a119c203ab63142d6778eb111367180d5e5184a90bdd94cae0e626c620100000000000000eec223518b82ff78bef4ca3fd9a6058912cdb39aee5e6a2fd9b8dd25146f8eec0100000000000000583010dfdf4a914b51046f499ba00fdbaf7444680ab7e3feb863806afc9d4fc50100000000000000afb29049c06d29e7e382fb2a19ac382d6c01ffed9245c850a4f68b6fe639e4030100000000000000bcd89a40435ce16862e78bc9f977dd61f7ccf4323a561f2c3c625b4f14056d6501000000000000001ff1b313b8a2225acd1772fc24366d1fc857adcbba6d7c71621fa533c6f2bcfb0100000000000000b3c46aa9c753d29fa79d466179c000bcc3f58a62d57400061da1fc7964d061b40100000000000000be46a715f2c4f42e0580affc7cc991091b2912bd6573d68069b54c7a4af736dd01000000000000004a2e56a7b960fc40444448289b8ae74d2e5b5ddf6cd64ad6f75032b1ab9aeac50100000000000000bd5bd494ec5f03b3e215b88b8ce3ffd29943c84148185e23c5bf435db32c0b0001000000000000008132c4870d7b794b0759575dfaae69e2c7952db0506bbe31acf62e1a8ee06cf30100000000000000b0d9fcea946625b8fc99c8a0dc94f3ab8b9bf4f315e9d7a4197f418ffd48be42010000000000000088dc9da2f1bcda377024108c69308245230b5803eba69cb9217bafe801369dfc01000000000000005f0513d540ab726d90347fc02b7574ae453ab7df6e5ccfbfab920cdb5d368e3a0100000000000000822ca9e83911d6bd793a882add566078adc7f015feabc642a3a5779bea74d3720100000000000000169f3dbc11f9c3193983e675784f5657b5c47da066daf107cf553881fa795fe001000000000000008bdd0ca16f1a1604df36c7353e47f4c9e97cfaf8ee06c178dfc116579b0e01ab010000000000000074831a2e8341c8ff72524f2cd7ab77dff22f9640bd673ab389c9870f58a6e00e010000000000000041fc50128f0dcbc06c13b70adb6094f87c01010e93e78f6ded4220d65ebf56b30100000000000000fc45ad7107892a400c44ae758f9a9c23fe53eef7d1335bb0ec1eb09c5830d68f0100000000000000b9f5a14a207d98aac904250f7016d38e70e3f2a9f5b739d70501fd6de13d63d801000000000000007a021d8c0aa92dab87dbf6cd49bb323cc0cae817be08b2afaa5ccda83a9b1164010000000000000027bc43cac6a099759f1b4600568b3ff89034ca976741244e3b77c6fc8a09d27c0100000000000000396927eab5fc2cec6babf27b7749c236b6dcab57f41da06e78db2cd7ef03093e01000000000000001ef946b39101d2175a00bae858beea47817c6f2a9630694f603909e76f3fdf5d01000000000000005750ceffdd37bd50009a81d9f2b82bb74e915f4a418a808af2e9f2d5b493852c01000000000000006d5054d42eb179d1f79a011aaf78df2da7a32d6f1919e5bb202b0df3d54e794d0100000000000000151ba3de7dc52510464ef9709f2c13bb870610396b75b341ff37d00d1f17782b01000000000000004590d65eaafa3b892d28ef43f8f7fd8a8e6b1acc375b5b0d082c80da4ed23a8c010000000000000041bc70b9742be19026a3b3bab324b986f5648be81ee9d8cd78ce746c9f016e01010000000000000099837600f7b8516cf16d134c70e7eca15eff44a4d51f3e3ef2f9405952e3a3cc010000000000000087deb488a2db317fec21e4aa3d138ff1d8e51fdfdea8ed9d02a99cab5e80d5480100000000000000c480fd6b04d8ceabbd481ef1b9b67a0c98957deee6da5c500c2eba877e039e090100000000000000af479dee032c00d85d5c49f48dc044287ba995bc12fc84f36895e9c57c950f390100000000000000909683e55740191af0916b0a6f5a31048fbc4a1bf206d81843682d1a19ae422101000000000000007ae479e40493bf38f8660d7b79160cbe7bcebb9d118a373df1814f79caeaad21010000000000000039c68320e1a15c97828d15363dab95061c43a1e51578839ed081a3e83ed01beb01000000000000002b372d7d47919faf7cf0513b3929ac36c1712a2a29be29308d1cc31ae8a03af901000000000000009be130185be55463c0a7a3a1119ed53bc85e34d49145e707838269dcbe61f5630100000000000000d8a03a691de3196553ad818de72c4c66360cd3a0957ffb8164088ec4fc2bae430100000000000000a9d495c403237a01bb79d21e2942a07956df23753bec402f597ea6d99e4179760100000000000000b602c49f77df2dfd482098bcff1c136fbace2510192c1bd1a2f8321fcefbaca401000000000000001cbdde2e5c8215dbb1fff9137796f6f81f822199bacbaf30e34c53979a58f2480100000000000000446a8b62ba7d554262df99f05ff3c3c530e7bbc5da5f024c6629585c9e8a159a01000000000000009883de0c060f767e8ce3f0383defe951f7d177f2cb62247d4c026ca42e9245ff01000000000000004da30407c7cf8de15d30b2398f28e5ddb74f2ed583f92812c4931b9531dc64980100000000000000389b7bfe4c6fbc88642466d2714099d3e5fc01f3a6b61be89d0d140969f4086d01000000000000009c1af5563cd87829be16261263973cc8d4ca6c5df0b001f150e1e72f183f875c0100000000000000ca46c56ca3cae34809fff0dfae000f77610b9235d1bfac674f0158fde58e76770100000000000000dfc1a3c30db79ffeb553ed1728d31e88d0e0dbf28a1a9b9cf955fa827e4bb1600100000000000000256e44210bb64dfc95063df97201b55309a2ac1f2ba12a167044bacbdffd36750100000000000000e02907fbd390e357c9c10909397f5b0f4ab2e6de55e5d0d4f728eac2c8dc16880100000000000000fcc82bab23e1c21d08b5cb808359b8bc81413c8767480668436bc70be8dd7c7101000000000000005455ab25570c7d5c3e79955a8cd0267d2197d8011af44f8e561d4ecf6c00d9d001000000000000002f4c42236259c59dc9584c0cdc5f387e11c6324b0eee522fdd3e726c5a94ac73010000000000000076ea2e98bc749e53df71999558883537af2221a29c9db63ab636bd5831e2b8900100000000000000a1fb663f142f72d92ea104465919238e8cbba96c2e103e3af3171e7610ec733301000000000000005d518bf0447e9f05a4df6bb15fa915be5083e7147b985f27070ef78493c9fe970100000000000000fb42cf7e9f7745d451587f3902b2845fa45b92801483ecbb50f2ea2c869a1188010000000000000068cf5d9d2e1c6f242313150affa25bcb07653278a6b868cd3d0ce0ca2b78f85b0100000000000000170662fe18881cec0cfa50bfec1a31a5e5771c6ac4e23ae387c3b10004c61652010000000000000089133f854ed2297db49ecf66a575106c24f0a866d8eeab58186d18288cd9c79f010000000000000055e939d64a1a4c8492c38f69ec8462e94a32be19fe5366ba7188097368f56e4601000000000000003c969fa14fc1fafaa3d89cf449931b8fd3c781296883af989518e0d46607b1ca010000000000000011f42fc39508e8e787fa3c7ab9dda501bb625fcf951083cfe7d683451fba85ec010000000000000093e78ea5aa0386d735807ddf266fb4e73e2dce796832ef50558e4faf8a667d8501000000000000007dfac6fd5e7115c77b19b829b8679191425881fb965bed900b7cdc0067f139d2010000000000000039c75a934f0c3aec91319c2a463ecc462430abdfeb13c1aea64aec895a897e2901000000000000005259f68ef009532d3af82f202c7e7794505ea7ffd013e591c275b6889bf3bc1001000000000000009bd44fb475939839aff273455851d8766729effb9007a0678e9e9b9d775acf2f010000000000000008947ccf8b6672ad323a66174fc7c8e02a28b62c551346bae2df0aeae52d2658010000000000000062d1270205c74202e7c0015f485d11864c04670fa8cc55c422a0b89f962235f401000000000000009a45028c9705f8546bbf468815961f73d9b7fe28d7d9fdec21dca64eee6fd9740100000000000000245af719594b56e5f6d3aeb43fe2af3b7305865b645d87bac2abdbac930831a10100000000000000bd824412db5d1070a549edbbec00de300cc79f494234c14318d4bb22b886e58b010000000000000097768b480d9ba5315238d3c9a494f2fb15be95142639fdf51debad3d283d8d3101000000000000003f3baa7e35e7c673e38711ec19116642a59b461e80f853fd0002b07d3b4c026301000000000000004a0f4c34e665764a6372744af837458abd8726552fbb4cfb4717beddec3fb0e30100000000000000d6e7f2f75eca6797daf45acc82071d7bb9f9ef7e49bf67cdcf1a3af3aecf285001000000000000004425a63d59fc7ae707d32dee0da003c3842477e8c299d87987e92be5c7a14bb801000000000000006b12f97a7c9cc9ee3dea1d6fe9d070fae4f0d441da88225a71d859c002e78d09010000000000000077225077a0399a36be04079deec0112c0b6a4095a24d2578eeedd53708a95f2601000000000000002e0f8c76308ddf0ffd54ac1f28278ec0527ddc7a15f82fbd9893d3be0db2a3fb01000000000000000300617d7072438bc83c0e5eab6de130adfb2f6088fdeced3c1b40072e5b26d60100000000000000e3c90fe70376a18a4a561fba2a38b3ea5ac7ae4f58170f1780c100e1dc49c39d01000000000000003dfdc14198f6098dea266e89f75cadb86eb2261b39e865a6cb2363c90358f0e1010000000000000087dfdbc9774ff73f75e180b76d50a4f2c8944149ab51b2fadc2ea36a5fb1e6910100000000000000294999aad773ab534a4dc790d2daf7516452ca5581d5979f63b61f542da675b301000000000000003d3b20f0469c448fa9d040bc754f2507df5f24ddb65f13c30908112702fc5e7f0100000000000000afb892220d0f6bd762d341e135262fed18f85972c3b9ac6b1caa6576f920b5200100000000000000b967c372eca26852db0dcd61d9f96ad4c6358ee77a50b19fa9ef7dc7b769be9c010000000000000051b2b3591644b60876758068eb879cd2b7814ff5827a82fa46c61632f6d2083c0100000000000000329e26119fe4360da232e61cdcea80f545f65cc5304619c367452a97e322fec3010000000000000021a47b7ba7e8c0fca174f172b4c569d3fdcd6a600364f40e6c41bebb8ba13e49010000000000000056e390e5671f499e22018fba8b1e1a46eca0bf9e3e93861197bf095d1fea4b5801000000000000001df25125f65060c017906a57606f3000dba8acf7aa845dc18fe349d76b51b8ea010000000000000034ddfb45732360d2935d9bb6d8882a13e2f674889520fc1d041cb19cecf902810100000000000000773a04490a10d39f99662e829bd45d221ab01376a39e2b0e40f23ce08bb28a700100000000000000cb1d42d58b9dead95b7385761b81f3fe7f83300e3571e1016e38b69b9d1e7f9b0100000000000000369cab8a01407b4e58c935e15b9ee461f3c508fc0d126da8dffbb00cf631d9aa0100000000000000351d8dec947f961741df732dd6458f174165fe86299a0b4e8456ebeb338204b301000000000000000211c9c863192f4107d1a266b0268b05384bb2313016a87ecab7375d156ebf19010000000000000030bdfa7ae0e7e06e1c00e7619c8c7ea52af7e45f7799dd9f8502ccfc19a0a7e00100000000000000f00e9c8aa956414636decfe5414d5d5dd0c14f51140ff0edb0752d32e37972ce01000000000000008094752407b875962b25ff09724e337ce65e3d57117473a7375fe6f6b1bfbf930100000000000000d8c87879b9e3cd570e7c2bc2fb690d422775e7d9b91afd79251701c22fdad0e501000000000000005a9e75c567e36d4d3677705e911a9bc73b97e7625c62603d75ed483af53c046f010000000000000096fc736f8208979332f0b0f976c46e0c493125fa6e19b282c7c41fd7fe75c8bd01000000000000004084c3eaf3e2131de24af8886cb5870995a39b6fd4dd8f5480f3b0bc1bf7942e0100000000000000272bb8501fa5b617f91508a2eb69f45c3d1128bd3dedf9835a33c12ad8538eac010000000000000037b56d20f4d2786a927defebd33ffef282d6242d079a705f1c458307aafab7c501000000000000004da15c350db500f4832738296a17ff09caba1e8499ca26322acc41d28d187c9101000000000000002aa65b0afbbb7783d6ed9e700f8badc83d30f5ca6ae62e699075a94b9e54bd800100000000000000b514b7602f8f083cc1982c617723948c0d71b5f18186b5bc8a7f59a8dc2f72e60100000000000000d8163e1f5f92cac78cf6e75ac39ca2e5ca69b77e1e8504fb638e73c5950289320100000000000000dd1af4cbf7a2eaaeb26c3247af2facdf7f784a4c2457ab7486c18ecac95f5e250100000000000000e756856218ce3dd98f3ff947dc4b8683ad9ab0989283fb54ce5af8c68a8d4b5801000000000000006d2f5b509b5fdea9d7b15f2ab3c69f631e28d69c74e74093efcd79bd880a73790100000000000000f7252333ae458dfdfe9f005ee5efac891bc6f5153d26610ab922f86c630e9f3101000000000000006e07fd8fe3e18dd9cbd6708dcf22795f956bab8bdc644c93961b40d13a2d5dbc0100000000000000d3ccdfe1b618b51ddef5ab9e801f4cefa1d6963539c88ad89ecf9b462a1fcff401000000000000001a191ad416f5f1e75e4dad138218dd58a6de4efc238f19dd49dd8abf4f81121a01000000000000009ecd936c7017376a01110b5afb1414f9c431876457ddad5846b9e5ace0679e2e0100000000000000aace5d58d941ebcc36ed44ec75057a9536eb7cd55c264c320e086517fb71b8a50100000000000000ce08f467eed01f7b3d56c59e6f78552d280c516e8cd8c8e61b41bd0cdd8fbb24010000000000000029babf37d84bb0a335b791c76f4b52f6f133e7465a1d30e16b3029ba725ee1e60100000000000000702bb22a562eaab9b9b32e2f7299dfc4b4f7250641ac5c9f16eae5f6b67a9ed20100000000000000d8795a4d9f4ce53c6e50ae1b8ed89f2ed315dd47c8df8b511039f84bfd102d3d010000000000000007b48518dff35d71e64fba74c7797a0f2a4a972f4071818b5d0653d011ef98ed0100000000000000104f653efc82e602beb1511fb4ade2bc8f072c90fd8f5f2051ab19aa918afd590100000000000000b765c1bdc39308a3c904c6248305050bb10ca32f9638f0ae471157ae93a7728301000000000000003bdd5e7017e30ca1681ca395d65713cdcdeb9c1923b1609a317d4845e4b062d001000000000000008d8f65c982c92658472a3b49e975bec33d3d1de1534acc7eefc403f4a6b83fe50100000000000000c4e7cc921ea9002373173c6a00d261c83bff74bc65e4a4a32f6ef3f8ccf77a5e0100000000000000375473ead394434b0ea4d00005fac9f0817fcff73ab27c38a54df4a4060c40f701000000000000005941e965255cffe3c6f35affc92c38aa862d66fef570f72e984f12d375fefb940100000000000000440da71d21a7e96d24587e84e837f7344841e62091302b39879327eda67a6ae4010000000000000023a0a8095b7f87b41026a0f7f1a8831ac6ffaacf22d205b37241938e11393b3c0100000000000000e98a14ab6031e95b12ba4dd05bcdb7924e1c474d15730ced4abb8895f02a3ea701000000000000006d15e1d9c067a16690776749e9c80a6d5f667da2e8ec63647e2b355fc5ba1b3a0100000000000000249fd6e0852479b5c26f54e56968801815117fe0aa7739160eadbc4d310d6a060100000000000000452da4ca36647ed8fd6e32962e3da7f39264f0e047458c070b135e7a624c32bb01000000000000009790e4492c4903343624adb6736db8f14babbca82330072bb7ae7a66d882abdd010000000000000044143440ca0aac28e473418fb60e855c8933da9ca15240eb7c57ad8758811d7f010000000000000056e2b7a822d829f395db95c79c75bcb575911e179d8900005f2b938e4217daac01000000000000006bbe9725cd6100de17fdc4eac37c50e0b160672df0c963ac6fc366d2125e8db70100000000000000c372d17cc175f7384a1d17b3609af7e19a6fa71f7c1f7f737016801a2ba07697010000000000000054a5585debdd8b8385f49dd12968d06aa407222fc2cd824073db131a3a87748f010000000000000030ec980417a64391fd24258917a9ccc9bec58057df1ce18af9b3772e27b8fb590100000000000000c3b162bb5b297392ed708b507341b7ed7a3aaefc96265b511d16426a048aacc5010000000000000022b28fbb55c8d1c6476d3071d25762e9e613530f4d0de6c31cc92d916f1d6aa00100000000000000a5279d1b25875dabffe8e437fd52d7ec066caee5f85349f8384ed0f2ce5b34ec0100000000000000b39c9b4dd65cf7bf38ec8e267f6e54db83d3ef9c9d913d5fa6e25965b9583a3b01000000000000004be4beee31e900210ce26c80418a1fe1022559c734e5bf39756d2a45846c979401000000000000000479b72f27c4ab9e948e209c221e15e976ea72f31f5eb7c52cd539941f1a6f91010000000000000072275f5c6d2c909f918c98a7a28f165177c53ad62e98103a9c5a77d1dc0365ac010000000000000080c16d82b12c29b949fc565a0b6fb805bf1f873701dd34112715da0124b8bb0d0100000000000000e0644a8b4e18cd40a0ac615ecd6ff53fa82492a9403d6a0a2d3f17da04cc594b01000000000000005b864ba7f47e1d3512b0de531ded35d5bc0ae463d3a78689d0abf8290a7a5f220100000000000000acd652cc61439b7ae83950a79cfec8cc75be7e1a370e979f83ca3fea55c2427401000000000000004c132f118dbc3a8d84a2daae0814fca1bf0618dc217313012cb23bc3eb012b520100000000000000f048b3ac57f63b55946ad7b1786f7b832fc3b950250d00b57b1e8309f2b89835010000000000000060a5eab208389938009ced7515da8dc91199156aeba501bc62591b9afc3eb57701000000000000001cc88ca52f9377e0d59c02a2091b3db6e32c4804b37452dfd9fc2d57af5a19d80100000000000000eb82de2c216609de8fbad4ff0d2c00622cb4c3a1bd3ea7362366cc1211a6418d01000000000000007b6ba4635f6271127a04f9a2a4f370cbef420d6d909b7ee8a42319793baea612010000000000000090317ecd7a5cd294bee9c28842fc13e22c7b7a986843d79636ade24d1a632754010000000000000048121ed29c73d8b7cb0a00729f143eb04d7a323f30f0d73bf11ef78aba30a60401000000000000008df0f34d87e40c908e37753bc4e282de02a25f9e7cbd13ec097d0ce63a7c3dbe0100000000000000a4dc11d3a09374c43df1b98462ecb6c175031295e45b2ab948ff8bfca2870847010000000000000092423611944864e12e30135cb018baf011093c0a040e556d3ac84f4b7126914e01000000000000008750d34451337dd4ebb89a8346f8af24b741f2fb0ccc600adc7101caee4932020100000000000000973f9cc2a108ea8d62e205bf84707f420e015d43e11b3f32585e5fafd88bd0a201000000000000001bb273f4634c3a3f5d44d9e3116c149cd81899efb6834cdb1f9db1aa24ab0ce90100000000000000c95f1b6ed9f85655a20cd8b6789536a8551f7782f1689e731f54b32de368d8e80100000000000000ec4b28bb8c33716f816c65d67ebe362da9723fbb400b6cb4571308c9315db10e01000000000000006c1fb669b10b54e02934674124d21ed495bd2a61cd9519b89e91f0dce2a6854d0100000000000000e74477bc201b2e85abacb23fa7d512ec33458a4fffcfb870d5b42f07d66833b00100000000000000545d71136e9ca898d1bbaddf30b53c380e411562a80c184e8785cca1366d155901000000000000009ef116030a30a43c285596de793a378d07f540b8bf3803d13a3137c2ddf96f60010000000000000099ac56e3007161274c96108ac9533acafd29207ad16b713136e8d63c3e24b6c20100000000000000f74a665bd1bd30632f2692941aee41e1d467311b024a44b79c12a2473b652ee70100000000000000b5c085ca08f19cd8132e306ccf6d9a2f77c9c17613f0e0d598747f407ff8796f010000000000000072bf45400f389306ec8bfaf415bc8286d3b8adc46b8a08c2f3a0c04c0cff6e2001000000000000007c063e9172c47480f33f8cd86e04b382660ecda2d75f47456604234e5f61cb110100000000000000f9b1974216289154f3a7d494b6568561c580b39bfd21dea11df76635d370ba3c01000000000000007537fa71ccda325be7a6af4821382dc9792e04ee12fd44eb192ac5da39ed748801000000000000000c82f2ef68046bc4f202f4c2dca80caeee2fab752e3b836397b32ca97d6b63cc01000000000000009002bc69256e3ef6d0bff3d14678154d53debc57823ef53e376295d90f8def940100000000000000f42e72fb0b31335285c9a2e7e114517bd144d7e2cadc894d0550de87cdbca9890100000000000000df96774817a9898dcb365aaaf73ee9ebdc0835c758208c2f8e234e60f8bcca9b0100000000000000bd56460bdb8be7fa6794aac7ebeec24ed4547bf59095583533a856a1772d53b301000000000000009e9ea48ea55eff53323140e01f09357b1bd5f45d0434cf4fe30b45c5e2b253ad0100000000000000d07257b2006ac80ffb16a46df3b72043d6716e5efd88b5c057299684b2265e1d0100000000000000c3611bcc95878b401e858bc69fd8fe7ed2b8340672e87b61d37b2b5b342ae1b80100000000000000a7a17b56eaa59a3f6323a172caa2bb24ffa87440b22b6af9af1e4974c4917e7f010000000000000039f25e11b2bb8d6b694a9006e7caf94f4ca4b0e3cde4ea33c3b0fea7661bb46301000000000000001a9becbcff7b2cd3298018a03f68b2fac299ce24f3efec135144e8807caa5fbc01000000000000004548f0921422021bab868a94509b13f46eff3cb9d6c55a3661d353cd2391a00b0100000000000000b9e0823659c375f45ba3b9d8988947c0e95cc2f1d06e0d94fa97c5571f15d0c601000000000000006f80dce3df6db3200b6e3d9a5620f5416078074722918c7e7ef10f6c51142a990100000000000000b2a7d81c0386932fcabb63d7fecc7438137d01b06ea6177c41958dbb18be5fc70100000000000000c7def0199da5f66211e71f869138a9418acfc6e15bdcf75036314318386a7c9d01000000000000009879b5297a455e5e2479f90b5e72ca67ff9878cdf9733e4b4674162b61f247b101000000000000000443b2a8fa77a5aa043ce1a5c9c96a586f5fd5d4682f5748b8d578bdb2e1fb230100000000000000e177e700d0438cd08bd4e4e3b3ab033e44ae94c63f9958e95095cdf02386befc01000000000000006f72edf2b3f0896ac544636046bda9af362680322cb597ef05ff522d6bc593450100000000000000f98397b18c14673add9760e95b53588365a9692e34cc5fdc40cd31a80bd0744e0100000000000000fe6563512a9685d7412d2bed61a760fd964720f257e207a73de798f6f58218230100000000000000c6f911c94014fd42c07623256a5d9a2af950c4ec070e25964518338759378e030100000000000000a87fef4b0565024f2b9aa6d1545c7ef2e33682779d9600dbc0356f3accc578f00100000000000000753d32d75b007dcf9cb6688333211807339ba7ad696fcce821f8a28279a90b090100000000000000b622218767f18927b7a8f2cc214aa7ebc12006e48928fe74a376bc016d7e2ca10100000000000000853191a0295ac06d3ea8ad3de31dd77488480da7e5c101922ee01f59e0de0c3f0100000000000000bf18dfb21373a89d9e4a620333ed3e374660fa2853e1efdd4ab30b53bde8e7540100000000000000a88c5352cfa8ffd78d2cbff43821c6f82147e9ce6b72cfc31b1388a5f4a3ee2b0100000000000000824c1129c32eba8d115bc87ed42a6d2c570fec0eb0f9fdb6dc535710c496e65b01000000000000000ff138815854ca8dfc8670c4046e1374125ac82b9842d34f8f7bdd69213d63c30100000000000000eb75a5e4a2e13fc445acfd003bb16ef1ba8d0eb9c8db1f8cde48e52df059583901000000000000002222e98493826736380b2581c5adcff5fee14b658acec7358891a62ada4478460100000000000000a8cdb071513e29dd5e673414760cb31abb5fadfa8ef408538231a59355ecebb4010000000000000099e6ab3504dfa4002c0f0841d8bb94b6f791275600ad8f1ceab7fb289daba46f0100000000000000f8382857300d5af20481eba7c53863f20b8612fda0e6f03bb8939c7343ee433b0100000000000000f00d449bcc7dad2be7ea0e99b5f86d0dc44c23414d66e2c93bd8a8a616093dfa010000000000000012a40e1893521aac001eff367c5fbb0eef42d44028757fbc25f8b9c00b7eacda0100000000000000e491a4abce65ba2d194a8f16262d86becc4f774dc69a468001e800a20e1dfad60100000000000000c3cf16ecdc1ad915b8db9fa942217c73bec1246bc54bbdba9814598865c7ff54010000000000000034d7851d585fb1ffb6973fefa90f82e2c9f289b413f95807a86572dfde1f262c010000000000000059549361dbcd95ac51e85387833fa6f9855986c0edb9ffab734471a69b93672e0100000000000000fd24b88779539e7bb18af137449721d88d005a2774be84505fb0f48e1ad18cbe01000000000000007046215bfd55242cce4bd0115a851d71b78e278cfe04a8ee9ce71a6c55a591980100000000000000d8653da036b5311bddf82c4e5c7d73de3be097293b7ad0a2aff970722a080a9b0100000000000000f8e3c19c4b384dab650c81ac6229184ef88e47ef399ee29cc92c9f962010f044010000000000000045bc6214064d607d7d4c55bad38e96e290bc797ca7c0eb4f4d01243c2cd9a6830100000000000000d2878579dd4a1f5a71ef7c12e869f342857c44e7855ba4ab7228a1fa4cd2ca0901000000000000001c66b8fe6de938369a91e4870d41590bddbc08d996c5bc29f736e736053d20450100000000000000f8517d86f22dbf6eff5986e7af829b174878db89b5ca44005ac035a697c78a7f0100000000000000447c73fa108e988d3574609382c422a73d5bdb65ba5af33951f0a28d69e20f5301000000000000006dff1e1330a1330e8502510324a671d01e1621a5aaba33201bd3194085cc691001000000000000006c060b03bb564f715224f1ddde6849a088dcdc38ab6d0a58991827ca6089c08901000000000000000b1f0c55f4a30344e27625eea0fd0d0a7586c5767c1dc6be98c13672a85a04e00100000000000000ac78b577d4203b94e699682fdaf8e6f5ae323ac32db75e544ffbdc1f572d91720100000000000000f57349777102332cff7ffea0aff467bf3d74149bf0ad15250f1b17d6d910eced0100000000000000e66333a184fc6ccff0b7c6f03d05e756599432888f609a33350e2db5048cc2020100000000000000af87171a27906f01fba5113637e366f4b7cd6fd265e38259cf2cc666c3a7bf2a0100000000000000d1579c092548b3702323aab03d84d8484be3b21438a023cb572f95003210516d0100000000000000e3d9a3fd01e545eff8c4c08102fccde1321fbbb0151e1e4d878b125ba559409e0100000000000000e788e45637fe5cee8bbc7410f8a8f58b3c7ec03f222a011e839ad0d3f0b0580c01000000000000003d01cc5ab45b30bf88c9a8645fa0875db8a96c04f7ad09185aea6efdd85bfd1f01000000000000008d0833611b71abad401ca9219e46599468cc72d19d4f6ae2be9a4a5193e2c508010000000000000075b4e29e2e784cd985ce6787a52c7c1c73aed73e35bc1d980cf0260469b5320b01000000000000007719fa3f95a8aea4920a5b4f2831ccf4689b5027963b8a26264ced54eea0b5c10100000000000000fd2490888a1a6b0f2c5748d0b06a4b0c95dfe2a003353d58c29ee884c6a50966010000000000000002be7a1d092e40aa2408e71486bb82cedbb7ceba92368cb5fd0d77c733fdca9001000000000000006c91e3e19fbef83b171e04097e2e7c0f370550650d58c8eb734a4b48696b185a0100000000000000f4fe6baaba24f711b7d61ad86e94cd1305c84c99aaaeae14774dbda48d15df1c0100000000000000172f54cc79feb641d22554fa0105f5b018ec4bfe545ee1048c1080e8af585eca01000000000000007572849404e26b5b8b3885feef0a2d3e2adcb473de6015c5c76dd515f605403d01000000000000004a2b606b7451a470d3d2de58ec1fc9910c0583385cd29c234f34ccc1587b8c5001000000000000003e910b8f2fd8ad5e3dd4cb5b93878312b6d73746c4c322a66d88380b554dd83d0100000000000000135f81fb449029d79d3dba9325c9cada392b836cff890f715004cc89b6b5ec3101000000000000004893ab15a5f70f76282317cdba1907236cf6fe8dbee88fdf19eb31f075a0ebad01000000000000000aa3f9bc3077cda0772294dad6051abdc22373160eba156fda11c52a1d928b8a01000000000000001f54ced331438e259edc109326ead214df7fc09324da91bbdefb9d2e66f8cdb60100000000000000caf9f0d92ad13738929aa787865adb728889be43330cec0c4d4d9fd80b3553470100000000000000863d4971d0fb9c7f43b05625608c48f58cfc6407ab27d93845c7c25f4003a18a0100000000000000aff01bdaefdc9a953d4a4563f7644d337bd74c48a9f1ff8f90cb95259371febf01000000000000006ab28ee6d268905288a2816a63ad42470966b4cf1cbdd4650cc7fa2b284a5542010000000000000029b8b091208c6c981345c5e0fbfac94f29e799e7c07b9bf6ab3f3a71b60be01c0100000000000000443d85da0ba5df791e17dafa76bb1963e6634b1700920fc3dc80ff0f276fcb000100000000000000a631c37bd7265619c17ca5f154d0cb91bad271ba73ba7c314ff3c95c02a4719901000000000000007168ed3aed1d68cdd3e1ebb4544a5817ad4cbb3b72a3b195a369f708d27ffc3c010000000000000006dae4ea9fa35f417357c35dd211b0db5fda67241be048f10ba43893c49b8d5601000000000000005a9b3c6ea9f3cc41dbc0c95acaa9e3365c51de07356a7eb9ec3b55fb9ed3d10c0100000000000000a33fb30152c5b6afd56d74edb8bc20b3bfd99eeab9a85c354c02fc5dd20db7fa01000000000000005b075f0988f3ff6d940933c90cec2e5f1d452441e57c6fd9010442b74604ca030100000000000000671075ba6bef7c37ef30f9f965a5e347d7a73e76bdc5aafd4aa288f0288b0b14010000000000000018c75c074c98aaba407c5972bf7cab45ba58b790620df4f2c62592569ab1c84a010000000000000025a9c770327065f434db78e8d11f9df7e2d8c8b1e5a133d0008d2a49879d039c0100000000000000ac59381d1603313e8235e0c61451ea9b94447c9e579fae87b1dac1dce25d1a1a010000000000000098de3e501bcf8eae77e82d31f6d23773a25008b31ec668248626107062ceb23d0100000000000000c3cb22e4ff7d963b9ed812c3a308b16beeba6c94993b6dc4700cb30c59f2c8660100000000000000af06e3c5ff3b773fea3e483a4214e6f45772107902c204848d5369d12d1e861401000000000000003bb0b8e8c69ab7e2ad90d5f2c1c6c649ab7a33e082ab707838d4676abd1278ba0100000000000000cff791094029678eba97fac92e2cd1aaf6f04ca612332331f8504a1a9ea8e4c2010000000000000019b5ee484254655687e90a52aa0bb36825fd345e291c63c798dd359d7d04b3ae0100000000000000598530b8809a6eaa8a8f08f7daf86b3137dd79ec23089f12073181a47a464e3801000000000000002c81c6a93dbb19d62ea1e47cfcf02a40724d94e90eb371fe7a3a5ae56ad10647010000000000000092d1a11066dd49361e39fc6d95f033987aed5f6d9baec5a38cb211c1d7ade2fb0100000000000000bb73c2afde2552857b151209b61cdaf49ec0a1ad55861af1dd27f17ed80fcd2d01000000000000004fb9009cb4fb1f5dcd17231b9ded8df73b71c36330df2fd92f1f9df4c5b167670100000000000000d152c529e0948f05631393212fd890e0d1cb12ef48eddfb8e63ee5c3ecad671d0100000000000000baa4b8e51140a2d2d01e163c4650d8c29f5806cf5f382a00e9667c872a2b70b201000000000000006386c1eecf15ce17378b4baf6226150ca826c165cf20a5a147f456797d64ae6801000000000000002a684b99e2b77bfa6f5f18f185af5d8711f4ae4f2ed3b11b993ec29211dbe1ef0100000000000000ef75e4cf5ab68a5395bd85a07204931630358194e0a8b80705f297e02d1018f401000000000000001a8735c1f7e3787a509b65076bd9b3917ea89cba519a0bf9280afa909da9c577010000000000000021534624fd655a8c5373bfcdde8d911ede8c2005dc44fb8e644fbc3307e56f1c0100000000000000128492d758ca8fd83348e4ba21b00cb3c61eff6fcb5a1154b744ea5022d12e5601000000000000008a718ecce14a4b95873f23fcb4cb7d3a0331ee249e6dd33c5bc5af69378eda840100000000000000701283212595b843ba2bf8e4ff00b7a6ce7ed3ccb2e6be8c548915ca89cb3fbe0100000000000000b94d03a340c55d6048f8f79f7e91f997d1dff957a9f37efdb78a174ce1489a9a010000000000000026952c9c8c36811549759a3b0933d6e6b40d67eca5f93490a0e6fe1d1687a8700100000000000000440d6f35805324d5bf8fb3d9ac252976765ce78e5b1c1cd5e92f02011ce3e6b90100000000000000ead062704fc6305259e5fa62319b4abd2546fe1264822224016c1c05b243fb370100000000000000222304ea99aaf36fa60212ac0bf68c680660b3cdc596b288148a16230cd8ecc30100000000000000373f2cb3d6edf8731b71e0d852ab041bcfb905de8b9922d063f35bc4daa839b701000000000000008a05f2bf7e72564ed6199b4a198439d72ecf851550cc19801119ced041533ef50100000000000000e66a70e30b2411714fe851e9b87a7146d440e655d02b746dad9acced063a663b0100000000000000dd62350f280daec15b32d9b0d49f2de7ad7935cd78851c1bbaba5b3c660f94b301000000000000003889d5459d7e46ff2c002a447fa04fafae954b1eca6f8768db0d604b0d7290c301000000000000000cd66c0a06c39d4e4f6fde27d56484cff46f1e2bb22b04996f728fbd4304dbe8010000000000000081ec6ec4e368cc890c551d841e67d7645d104392173990ac12b8c573c41833960100000000000000697b9b9531b00204163121506d272859e324e39afb267be8eaea8eae5c3e7b4b01000000000000009079d1ef3a4050c4f88e37ef009f83796e42bba6af68148e3c22902d377977d601000000000000008728111eed39d1519586f95d9b4f1427f477f6a7eaef2aab030ed3fe039e35490100000000000000e904ea4ff2b1d883bc4242740b3a93fb925d67661b49994e0a89c2216dc577250100000000000000a000c0b660cfb5cbd78f4d79eca99983c2a15f099dc7134920b7f367d9443318010000000000000040e62be8934203b444b503efcf6ca33356841c72402615fa43f5583a9f824f3c0100000000000000b80a5b7d9978a80c639cf9fa868de3c75c32ba7ff8a7a7a909c89e63741192d701000000000000001673cf386933d367f0a57967dd6fb55746bdaa8db89e10659f927860e881c35d010000000000000078bf0770bf288236cf92974e69e6ded85f591d10f6b9c875b1bb7f94c14b305e0100000000000000d6e4c7c7b0e14d7942a45e85c99dc3d520b5a8cc64c21d4c76957d4b241d68f90100000000000000f342e3bbfd9c4391cbe352e3e3eb70e44e3d90c2cd776b5fd6f93e617abfd5730100000000000000ea7897735f2b5f06aa234a4da5faa82224d0fee80b8e19ac26ea4889f086d65201000000000000001fb16dea0a10e8ec022756f3b67620082e80494b1366b4256358d23f4e7b17120100000000000000bf33edce253ba032d61df16c2a1dfd8ff2bb70d8e136c2e2b1499b6265ec1c4e01000000000000009742f968c3b199a35678c43a06de315c0dd3aca69525fa8bcac1aa8a618d83740100000000000000febecfe4a84329080802b65b5019beec10389cb1c523a6c662dd1914108880f201000000000000000dcaaf090039511495a003e80b17f789c5ef5bbcee067b3af530d66393ae06e30100000000000000557eb6ec53f2431eadb69f40e43b4e5ea85684cf91608792a16a4e2c529cc44b0100000000000000fd2e5f5ac6bb7f64ad8626d5a5250a719ab3976d6a670160fbb46fb11e0179610100000000000000ed9a1833a6c81018891a7ecb7dd3793dd84285dacfd50646c3b726c448ddee990100000000000000063da991ed82f441ff33955ac9bb0ad84a9c2281d3b6d972b54159629753f6b80100000000000000e4802c8d8e4eec0abb45228b0567ea73f6679d3d386271a9b7b6a17407a651f80100000000000000faa0480b90f0a55c492c1517affd4aafaee26209db3f8e18867a98c60071bb9b0100000000000000f43a4bedf981989c316bff3800fb4938cb18bbf614eff79db815291ac4aa621401000000000000003f1b990676a2827a3df1ca4c800eba52148557e905f97f27c95e6b0da03570a801000000000000003f1412b409be8d4dcc22bf40c1f6e966655d36d85e8a9c62ad7c0ea93b260d5e010000000000000073649d67f32095c6eada64603dc9231f9e1fee80800cd1b4ac85398ccdff630a010000000000000042a9bd8243d8bf7493673dbee57b8b82f6e0e5b1a399225c97c1c54957fcd62901000000000000001d84ed213dfaf24883e66d1140aae4763d871f213536929b325a2e860d139585010000000000000003ec969a638430c8933bb155ecc1f7871371c1269449f531efb40bd4d71339f301000000000000003e162bd2778a2960590dc89c66cb510d17dd5ca233063a722d0d184d4b7938cd01000000000000000f8e3a9de3d7711dbc30d81c09e08224e7800c1cffa3a2bf0d10bbccf5c3514c0100000000000000627d7f4a7f0996882466534f9080e33831ca96740030c476e957fa8f512bb6f101000000000000003532c9aa1b979060d183c3bd7f0166d5e96b8b1a5265f526a2f79171fc3717cb010000000000000046f4df6d2db179e7ba6f00c0d34a4818e478491e4fcceae9ae4980baf980220301000000000000002e1e8bec92ee9e40af70aa9cfb99b1a03abf04d6c375b0bb4fc7d01ea575d5a101000000000000005fc2f4d90a385bc00277f9449b4865ef2a8ebbf6b8e4a07d499312b46f410e550100000000000000407876f5b573baf50c8697eaec80519e889c294f18ac5e3f264b355886704f1d0100000000000000804f95ff8840e969c614dbc9c46bdaf27cd075885dcb5002b6d1eadce103f6e10100000000000000b321c9509f24c2451f74a147872adaa5c8f5e96a655c82ec02ad75c88ef03cca01000000000000007d0e3f83a891acc727320146a9617c0cf19ff116d039fb6780fb81aefe54ca320100000000000000a62f8eaced6544cabebac01255082ab60c430d96f5c401d32893e70acbacf4ac0100000000000000904955032291fe05f332340aa3398482030317345402b96b9176e0eff076518a01000000000000002455d8427871e5555d5e572753a89efec6caf33e4363f2901a7522b33af4d55001000000000000009b565a74182352df27bcf521f69280e46abf9239e01c978c451335d8ac7010550100000000000000f258dcc9e8148cecf85b8936960bb4c147194223de10256a5311a079ee35ca150100000000000000e70381b9eef355ec78b7f976f46588401a71f20f95953a70338c51b00284144001000000000000001f6e86d09d2395eae6683aafa0dfc9c3bfb2ce2077a5a50a7c48801311d92a1a0100000000000000936783098d036ccf3bffd88ccebb2c77063b21f02040956fa62e548c8f773ac90100000000000000ec30c6bf34e2a4b16d35f25264f729ac3a59f1cd18a4d51888d802c59031e862010000000000000026c2b10a767b839277fd0e142d6a7a398b96e8c55f8a2ec3126a2c7ea9d8dcf70100000000000000947858e31717a9e37937e0a9655d30e9eebd4e80c0d2e06220d83afcff023c500100000000000000a032d4495d1908c856b4102eb52393be1e1e45c09df07dfec747275e745c321d0100000000000000906a0cf227274053ba714070b8ba0644f4d799717638dcaeba13252c553810c8010000000000000004321bd9f7edeb5664433eb92111c3549502aa8900d4a1a19a21fa3b020ad4d10100000000000000d8b9fdea27d5342d395ffa19e7af37ba5423574439ab705b9918fc4e7dd9ae3b01000000000000006aae79a828fc7eaef135fe195a3a65048501565bf5d479361d572e100ac78aad0100000000000000f2178a9c2a562918b17dc069c468467acbb7a0480cf9bb6461f844ce79e5447d01000000000000000e0aa91dd14c00f20c31cfc3e8e36aac8779fff412963be58f5461c9497870d60100000000000000b39ba85454e9934075bd52be5067a44be6b66026e7ab8756b9f4acfb9f1d9c6c0100000000000000229b1c3aecf2cb8c5a3a932cc12f6ef8865210d2e6d9c25eff32ef2c7ea508b00100000000000000609e318c37dbd6c9d04af59eae423d8e2a2559f8ce1e1894b5c9033715dc5d8c01000000000000006670a42fa2464e25cd64bb3ff6eb82b05a79b1dc06b4790d69236da07b083e3d0100000000000000eee2a34d9ced58d32d8258ea5d3603c7b08ac02f3c48cc455fd8c707865243780100000000000000a273042753481a4f1584c73a660e7b111d1d88d4cfaf0e8d69010861dfa632f40100000000000000f9d3384b5f61b6da4e6fcf7a2cf4ad4472dcfa119ce5c498b0fc55b753d318010100000000000000bef3eb8d78987c714f9e28a2b6000e581257c8fab3e9fe24cf4249772fa0ed5c0100000000000000088e7325d1e1ce9db835c14193c92e0d8e9b9d70ff12c648d026d9a7c33fa9180100000000000000e021640bf5fc34005969fcd968eb0c2feebc73daba10b3c7e8f6852cd033750101000000000000006136aac262061d0ad804a7f7afe7d0e13e72f518bc7142339c6cae51e36dc36f0100000000000000d6470310c6f8e4bd3dbe610b2f477c9ea5c18cb96aea4f9dc032ba6c42ea51bc0100000000000000628637c19ecdb1b32f0f296dab0635b09a0adca1e1af82417e26cae8b4d30c330100000000000000809d074b3b2cb683d677e684e6fecacffeecafc07ef9f3c442bccdd8b93a36ee010000000000000045c6c6d665c2547dae7cd10a7b368b4ea7f5c78d994a1464f8969d2691a4dfd30100000000000000223956ea7c11fc0aca1c345ac85d92dc848d4e851fe996901befc7ad9c128fe00100000000000000a4372f8cf393c86ded61b8d659dc148547c770df78ae00d9ec698ddeda21f0c101000000000000001b69b0e731f54451046f38a58e32879716a417e2c4a3cf20e5ad97bc1a8f081e0100000000000000682dedae8b6eaf47c7818743d902d85026ce30e2c6e60ffc0093de91702e6ac501000000000000000a0cf6a68aec54947f2e3248a8d1121bba015f2ae47c31a15d0843cdc0d10e4b0100000000000000ca388cef1aa09116e653c1b7e137f35f126ef3003b8770c38b2d60650fec16950100000000000000068484aa96cbcb8ed74cb61a7099b775a37547a5598a9a59cbc0179adbeabd920100000000000000f69ec54999485126f6c088cb19c16337d6a9dc065ef9f2ef172988af12dc46410100000000000000cd31b78e5fc18ff26504d4c21af98da25b34614a63f4186facf8181210fbeb2a0100000000000000b7066ad21180b37ad2364326590d14b7dceebfa6ada9a1ecd37862a827c2147301000000000000001553df16b2407ba057003df7ceb81eb7f54bd16901f673a200769b277febcc9c0100000000000000642cb6b5f40885ab7fe39ba824fc236d39e714d43c669f392eee7ab7c16407700100000000000000ad59bfec36dd2a929fd67b37142d5084381670f43cd33ed21851a082bbfeec6e01000000000000001917d64adecfb227e34d24220b7316e49a5c284ff32832be2e8ac41dbca6f6d3010000000000000003606f8c6049624b776cb81fbd0e1cda9228cc651f9c24d594e5a0803362501401000000000000001f7914205d9b784d4c5989beb11e9b9226cb3f797fa7d4291d2ea4c408c1da0a01000000000000000a1fc28ce5b68d7fe45b2c4e3d33ddca31343abf0f9173ce0f5cd14ebf1228710100000000000000a5a5f00adfe65450c2050335d37af629e1c2fd47990c846e7fd28e3f1a6598610100000000000000c48cf711c3607c16a054eb8aa33437d9c3037d4073fb4f3ba83e266e8f1120700100000000000000f9055fb5fbfe1999c4f7a9a0399b7c158c71617c857f753b3487bbde2e040273010000000000000055fbf3a013cd3a24e5f14a1d24df6e71ee2e11813d13f7b4fc7aea3a0e2e02910100000000000000355606b3099d0098853df7b7bb7e1dada9734b51616af90f35ef3769ba83bb9b01000000000000003e4e08e859ce9ef9e9d5c889ee154cdf2de23ed643353cdba04c2d601d4ff4a601000000000000007a9a28161683a0ed609909d45a8b01ca55c13ff85f1e027ac6226b64e427ecef01000000000000006ad8bcbf82e8f107ba0fedfdeacce6cf6edc223203f5823ec1879e80a3b6ed2c01000000000000005620f3f2d51c1841ef7ad21fbd3ba88312b2ef951d9746b453c0776dc0e2a90c0100000000000000c158712e5585643a24e30e2718af7746acf6f1102b9c1ddae204e9ab5513e89a0100000000000000aa277b0b7866b3d527b21146a0b921289f8389179335608ba9b09c55481e161c0100000000000000d0a979775c50164a5e02605981b6d7ef7d1dcc280eb15f1806da89ece6b404970100000000000000cd196b87a0d5bb5c51c84f1e9a6f2f42b34ad5243aec4fa82821444860ec8d3d01000000000000002f0848e3068846290f1f1e1ae893885733c9c1d9eb7f4d1dacfeb0dade09d7ca0100000000000000efa920f288190ef99e7acd435a52a0cb659af1f16dc6c301cda5814224cc65f90100000000000000196c56966b03c628c81a6ba559d3fb51a2868d5ad2654669c7833f475a852dcb0100000000000000674c7ad7a08ea2c1f65c975e0dfeaa1f437ef06b2aa6e50e901fd0c5f42a468001000000000000008bd0062272b767c1bc0882d059c8218438f1898c2f446e083788349986ba122d0100000000000000cc2c9478d1cd5efc3f5a6a342e55207e080362d7905fc3e6ad2771a4b911642e0100000000000000546da02e3b0f4c6c0ef31e4b229af1caff51727c7041dbaef2e91cae94ceb1be0100000000000000cf6fbc5caa1758fe5400dea267c74cadaff7de493287817db27fed81ca7ef17e0100000000000000b3eac6895edc3dbabe6e81ff751cb595bd5f3338931d97ee977580e1f2a55cdb0100000000000000bdcd9e9ea5bb44a220b4e3ea0fe0c240a97bd861dfdc62c39680c9b58e10e14201000000000000002f4f2e534cf06bbf93e6698fff2b1660e538ce91fd7ace9cd82ce06e45fb451b0100000000000000fba9fb952708c88061a531851fc1f8047d50d801b445e8264e845b01587957c3010000000000000042cb925144094cbe989a77c7415ac9c1101c093e3092fe3839edf0e78c759e1a0100000000000000a6fbcb20263dbb5b43f3c785e3a85cbe26f6db91b5be5158746477bb59488a21010000000000000047bdd7e3eade8bbe1398662277264520cbc913ef018528e8068348073a0736cc0100000000000000b49bb6baf5c60de937b1b2ccb7fcc202220734d6865d127da92cc166f61d75570100000000000000a0254ecb746f39e09d90ce37e2aaef9e5b59fc6b3be3667d4fddd083cfdb23090100000000000000888367fca649f79e57cc4364504983eb84abf891de5f3a48bd4c4861b594d5100100000000000000441b80340f94b39f8f4fc3fcc182cc0378c9d76934a3e6a7c76fe57eeb8d43cb0100000000000000d0edab7060d93bba2eb2fc4a4d5a8439e0a188b91e2659b7a341318fb3f62d1601000000000000006e21c6130d7b8103be3f58793b11c15ae11bc862ae961a4b9c1d3fe50707df7601000000000000006a29e0cd769e80e27337cd860f86765674d9a62017b9da8e6e0314fcedcb4b590100000000000000f0c0041b4561cb7b69ec207077d4786b962976aedf3c87fa8d1de769b9be7f41010000000000000008c2b4a0beafb5ff2dee737edb98d9999677f9166b134cfa706894055a4030490100000000000000b1131a7eec11e667238e781498b545ce5cee59a614d24c71fdcdff1b513f96550100000000000000b10f706510a7d0e7d481b6ef0c9b5b1dc95d5d975bedd70962720545dfb67eba010000000000000049a9dfca71662b25806229f2435ee0e2185bee68cad670c32cf0f3dfa2397dcc01000000000000007e38fb61be13c218f7b2c736c0e14f01f6d259090f5a6107dc2ae4318809acab0100000000000000515acbd683c530c399002294eae0989a0d23bb79afeadf3470c8b84a515c338c0100000000000000ef66d17a3774e1d7189ab10a4f0ef2231087bf8fb8c7fad01c795d5dd32911780100000000000000faaa17b341794750870069465c03c6fe06643720fa67e1df93ce225d4ddfe8de01000000000000003a27c6cc8d26d7b4baef02a09f6bd76b97f02fe5452ae2a17e6c12d4dc55ccfd0100000000000000f2261ca8d76c9f0a983450e8df061eeed617edf8c07a04c11d9f1d78abe8dd6d0100000000000000f624bead555e794981bc9f131fdda4477eafcb4c4499d83931196400774bc3ea0100000000000000137b000c924fce826a5b634d4a59a26eab9e15ef2f68ecafb0713b9059c6f63c010000000000000032ea992af353d5b74e716f33cddeaf928d0eefe32190331b4e6e70a4fe2700160100000000000000114f905e54f379e68085ac4e99d4a251747fa32072899d5b05d28f52dc48e5f5010000000000000021898cfb7c00c6b8ae87b92d94b43252940d85807aaf3b9d5847ce8a3fb15c1e0100000000000000c770cd54b8122222ee278e822b651dc977a41f840d3499038c4718bed9c74ce1010000000000000037abf0b2fc2ec624c9501373a61c7645424a7569de8b852778d20c5c09aa71210100000000000000cf2abece2382798fd19c1612918e7e5c223a796bcbb9237ef0c9271fde645af4010000000000000051534ac5337a881808430c8effdf4be6d9fe62e5c0cb5170bd21e9f927a580a001000000000000001a7513cab206324b81c241adc0f6dd7a6b9708a5ace2efabe39e86d97251c6f4010000000000000021e768286d9798502cbf12d67891e42927426a1c12e68a2104bb00321053464a01000000000000001b85affe84122adc5a785fabacc37dbdd27bbc9ee345f6fd569a4a527c753885010000000000000050618b39c3c5868e69a74e0bc82ef36669eafc8721a565475ebdd00c695d4c120100000000000000ffedfd2e8910ba49767d6851ff8fa42e9296be52457314c143c5cfbc46c823150100000000000000ba8a5096bb4baf9af1fd7c625c1cea4a4eb6d639c6775eab6c099f8f3f45325701000000000000005d11f61c065cee6aa9211a1afac7b8616f3048a9a25233b7d7de1e694bbbe93c0100000000000000650bfe667cf2fcd043f3df72467adada00c6971deece376c4f72049b24d2ce2a0100000000000000ae93eac13218bb8483e6c6a9f053bed162826b64d5f9872aa7a2d4482eefba350100000000000000f8f9a4a047724f3af6f1fe62acb02fd9099359f289641b4d6771a360f78d77d00100000000000000deafd02beef9ca7683624498b3af7a25b9a6c70c1b2625ab36cbcdb80c5aabb60100000000000000f0090416e5fd3c1b648335cf63b97793cbca50f1310a66a6c833e0290a2834210100000000000000a8c31c43320fd564715bde3089c6cd41ba4cffe5e04fd2d21d739867af154b9a0100000000000000cb78d2a6031246e25c85d0d34943a933824b95b4828b22cb8d0f2ad1ef144e8d010000000000000048453b1ac92eb0cb442669a5ccdc4df6febf6a65cc1b27646aded11ef2d633e80100000000000000923a9d1f03afc78e04020b27694ae4527a65552f8a2caa6bdf6ab195ba2313a0010000000000000086431e83ffc4ae375405a65baae4685cccdd8450d2198d27803dd9b20636e7fe0100000000000000510df66f2a615fb1b454b13c89bb12c9204938de71d7bdae710f7763ed6bf6a901000000000000007c16b9f29c88023cf44b3ab3ac04a5011908e72523f01c95125a97910bb522c30100000000000000b08ab18862adb9ffb2f14e50a6bfafaca81d53192a47e67c5ea0042ef2edf6c901000000000000005e17f2088755a8e57c2b0e121618451ef1afecceda9d5f57bb9b826e0616309701000000000000007c3e1f733373b72e402b4f32242ad25d79295419269c6efb48e560a052cf566b0100000000000000bf8a1f801ae86a7de5bdb88d85186072a15ec80ea5dc5b9dbfc402ec9764f2ac0100000000000000c9d8a62ba851335d6a5a100f9c573a6dc0e9c9621d6ff19c188ffe8dc0f6c499010000000000000050d1f5c6961652130a02d0f6d4a4e3afc689ee897efe00763a4bee0791bbcf330100000000000000bdf15023bd647e578b41f4d4beb909fe507c3fc4effa38fe2d70856e0baa440a0100000000000000800eb29e73a05fabdca500dc630120b269fd72ba019b75d6370d09602a9833490100000000000000d7b58c9c3bb2f0b4d67b48436c66c696f9b96c3fa266d04aac31b6843dfab1660100000000000000ae76d4dc0e39ce0c04045b25948ce2ab4894c31864a0b1f41ee73b305a3dd72901000000000000008b6ea5816cb1f2db9647bb03112b2791d417fbbb2c3db045df915663de99ea1301000000000000004499abebb0f2372c281a47e5fbc724d593763c0782940be0d8e5b20a01999edb0100000000000000768f685e97d3ab3edf750758711122783a75d378a24dc665d47893ee933f090b0100000000000000d0fc32c9caf002576e21262b39acc38b681fb6292cb206757e847fefb5b2c3290100000000000000547f505569f317cc26ad477bd3998efd6dabc3c550b866fe9636b02a631a1a84010000000000000028d688b7f43424d84ecddbef00856abeb1e7adaa15cf8ec395745d1000a21d980100000000000000485c1f216b9cd28985c83d655733c3ccbad15f09a5e6f33e57b3a05cad5ef5a701000000000000006c35cb154b9f6d249d245e7ba556e1e63d6c506ef2a5799bc8d44039ea0a571d0100000000000000bbe0fa0734fb715a39e12ddc369c82a9dfd2bc6be11621ca94bb76fccc27ddee010000000000000008fdb66483530ff0517a275e519d8402b41d5391b34a782d11317b9a45b4b83e0100000000000000ca8df3f7d0735b2a04342e35e8c6b05a2bd1d42cf0b8730ff78c4ff015dcb53201000000000000009815886014fa04deea13300299d59537a259acb12a6e9da56f534444642ecc160100000000000000ef25dea58c83d8a283b45897c1dbb9481463cdcb0f47026e46c99a1691e0d6d50100000000000000f4b738e125d2c2f1d0b23fccd2ec9ffe22c8a071b99150e7a5911a60810e8e14010000000000000069e13c754ec6ac6af554467afde9022234b070a0bbeb9605cc37ef195466400e01000000000000004c46193976af0340e9c20b3562ee5481e85c05b05b19bc8312671f3b6a58759b010000000000000080fb91a2a013a874df03942a29082cf59b6944cb9d065af280aa4a51c34ad0190100000000000000e0544cdd05e44020e65434b03777b7d4170e292a8b178516fa592f668815a35401000000000000000c97baf8cee7010019924f22aeb1b0995d1646b541e9634944c2b74d685075a101000000000000007a0f91885ebe476cd8e83c67c5c64be9b61a7c162156ea7a800537cb7645e3fd01000000000000009991a4f753dd0fa7f1ce0de007c1359211082b2e3348e4b0a307d49b23ed42b50100000000000000ef737c06277a7bb849b742660104744e29ced9b719d6783d87d89fe1834e854c01000000000000007fd5d11510934ad71239fe23d8ac93f0ed20aab56454e5a46b776d5384c6eb27010000000000000038c9fc4bcecc27719d50d4f4e7729e5836581a7c9c45d0eab220987f851c2c0d01000000000000003213dd7114091307f2df0d1146173b63338fb2324e2dd0c820bcdacc444137420100000000000000f108357d16f22a3db50e9a7a73b7bc9760d94e0de8d5baa0fffbfcd31759bc6d01000000000000009f1f6441f7f00808f96c79bc028ed2379cd62f8567b6fe5450ae0528107c0d690100000000000000b66a17bd3214aa5975f545d4932db223d616356995b42d736d6fc35a6db0e867010000000000000038bcfb746bea7b98dbd9d264f2d89c64d9fe32f0161f730bde57de6de6f9f6e7010000000000000039ce96efdcabe393378d371fe3a712e709641558798a82a9fc8c80d332e272180100000000000000eeec3b1e29f33e611c5ebb60205d01ad4cbe28d662c884219daa13e4aa16986101000000000000003e100fcc7d8a4627aa85e8fa74ecf5499d5c0ac9200a94c87611d5c49d2ed6da0100000000000000519dea67e7f301cd163de400cb6199691ef8cd5228be48d6f8bb54ce152b16b90100000000000000d75d44831fc7623e12762eef297c063f203013f1b30d9eeda1aa2bb49bbcba740100000000000000f2ba08d35922ef717f8ec01ef441202d4b4c20bdb9f8939d5fe785ac2d4e42e9010000000000000072d006433e1a190148dfea41ad04f6fb8cde6a46b0bd6f105531734d04aa759c0100000000000000f8910b16018dfa2afd231d8f1e6dfd64a0ddca9b47de2c3d3ffa194d3b3f0ce00100000000000000e7642c7dbbb311e4e809803933fbd5ce9358899797d622fa84b9ea4520196bff0100000000000000cb3290b8ffc2ac27e8cfc9189d917722b4d0d5b5c438ff2f59eb15c27ae6318401000000000000005c2cbf9e41586e3aa442272706752930ee9d173dd877735c54d05b18986dbce4010000000000000027052d0093d92efa297176b10ed955cb1a408f4529e9d007abac94b123a4fa760100000000000000098debe17e62286b5c660fca86d3e29aa9794680b817ed0775243e167f4433c30100000000000000caf7828fc405794715e5656964cc2620c1fbf73e76547b5d0ab3c3735a373dea010000000000000031e3bed03abf0622a6d9be8eb1d616e83bb7399930660f152d04a8bb9776d4ad0100000000000000207e7223865ef97f228072bb02cd36ec4954d95ae421f25c77d62e16ad33839f010000000000000036d64c0287041fd75f93b75127ae06b4fbe094d9077dc07ec03c538f84f3145b010000000000000007ace7565fbc814c2dd0a2073e2f11a2249992e883b1363575da86255d161d20010000000000000025f6ebbe5edad199dde0d7714ec81a4468b7eda91c5b36e07c4c7df752e5c51101000000000000008c79d057327db127ab03f7ffbe2f4db610441b12bcc90152eaee43861782fb3c01000000000000009cef809df3ed90dcb89f24edb21c629606f27dfb1b937629cfea79e884b020c4010000000000000079a9c4a57fa2f101f110190fd36ac57f44916f563925966d9f235518bc992a5601000000000000008f7c66bfd7969e222883ae982b0c8f669e15984f59a8799373e1261b8da2fea4010000000000000048966517fc6072b4c66260e0189797563c2e7031670240d1c6485cd6f4bf227101000000000000002408abd3d19664453ccafc99d9fff9a33442d807ee47e062ec68ae95c701be4201000000000000005538c41bde6934d5b97f188f2fe29450b17ec70ead2dca727de5bd9db54f2e420100000000000000a5b013d0f34e9215a4e64c4fae6fdd90bb700c7efc13f87723e47bb12c1b8e3101000000000000002a370587628878df0f3f1e27fd71379596ae279282d0f3600158e64ce1d11db7010000000000000050575b31eb025e1396f80d58639768baf2f67bba5aa31cd6ad711a4d82b612f10100000000000000d013d725f780a99ecd7543ecf00d415d6f1a4cbca8dff0c5cec1942a9e6d0af701000000000000004ac8b667ba68db10b7c9cc0a32db47d0a73bf4390ec6c748cf4d9c428a16f73101000000000000003410e60ea4234334900a6c72506694f590113be13698143ed260c09ea2a60e950100000000000000761b2fa233a93ee93cbb98b2001d3a55b6bd775f7edc07eb9e9b2fb28542b2180100000000000000c5043d4be2f1da401902a732dadb5b07b782338b2ab847d14affb90a0780573501000000000000005f85835c1c4f1b12ce3a95e7be77c608a2caff2b82296952fabc993f25fe9a190100000000000000530a5e325fe482aa3e8ea0891471611b4ad3e51f7e4da60c63221a24d39ce5af0100000000000000775e36b7ee208376e4e2206abaf01c365fbfcd0094bec4fbedc75f627f2ad4b0010000000000000057b31e0fbde0c291784bc082828e68c3756ea811d4e6e393f009d8dc16b692bc01000000000000003a6b5e6ef88c711308092f260193bcaa046f0a6d5be9979d29b444055d3abe820100000000000000c5f7462e4a5f088fea52a164456ac51b75aad70cfafc6b11748db4869c1b04870100000000000000c40f493f7c510cd20bf9e83b0addfd0cec751646750b400ff3e4bff05e14257501000000000000002542d874c5ebafb128e639dc6217ebb1642fc75ac08195ac7677ca03560cca4601000000000000006866eee27e8c9ce9888ec0f02f679a35c7fee66c97c08e9004fd2e35327419460100000000000000c897d3de7fb3bc3ef82d1d6bbeded8a6c681a2b692b164c0c867ef7274d4a81b010000000000000073d2895d842d5efea078e5a641450cd0486bb825e4aa6ef0062c69a28fb29b190100000000000000b274ad146b0410d65bd4a800c5a0aa6e8ef03e16b4cb9c06bafe9002d64ce85e01000000000000001db3f0b7f9f458dc7dc9b74c74b4b391df5da4c0efab615a77e3e680550c087b01000000000000002235bef6bd606076633af73d6966ebb718e736a7bc99cddd36e0a76ba61ac6f00100000000000000e050af34713931492ea47b3d361957ee7a6f6d5ce01120d0e9e9fc83b89725f901000000000000006ce36e20de0a17288081ea463d1c4ffd91dce4f8df5a3b509d96071b043476f401000000000000004f1919871c6e1f02f93d66a614473cf5f8e54714b72dc9013f20c40360c3ae4601000000000000002c0fea7c1ab260cc5168692660a0fdc681cb888ef74f19eff869447068d1f88b010000000000000040df68f798d81674c4ccaa60cdf05864a92987447bcb15402559f02f9ccb508f0100000000000000b17888eb419dbe530066187a8dd846ca99fb1b6790ce7db4d686aa6ea60007f3010000000000000049b3416b289edd5ec845dc88bd93b7cb0543c8733717bca1f20e6d111787249701000000000000002faa77d3f66d61232c0ccae9548f7c13b21dd49810ea3fafaa39491ef7efbcfc010000000000000089e615beffb1af587759bbd98a780c00874c454d576aa9c662c803c78f558fde010000000000000022506571ad53d250fec06159b1ab4ddcaa6637b7a1b81df228d76fbcfb8622dc01000000000000005fb20bde1e22585bc19741bdeb6bda59adb3f0b773872b3c358ab6e0a924fb2601000000000000003670056c5a21dfcb4ec05a01129163e5aad5bdff5782f7b8b8ba4808584f19bb0100000000000000c5160ec596ddcabf6b90bfdf3de3a769ac91d97bb923496c3feb70d9b31853530100000000000000e522c081114aeb222fdc60e941f6dc55ff820388f99558c189c46806e6936af40100000000000000fc4007bad5d9b2df890af0ebec30b5ed607830ac494e32b83970c7820e9b649f0100000000000000c80fbb099268f2b6383e094ac31a348dbff2b69e83ca3da985d8f2963449d7ee0100000000000000c103a178889515cd62e64bfcee57ea1b178fd3260f3d8c0e4cc36bb99f45594d0100000000000000ccd9a3ec7bbef923b8f9e32b120defe0b1e67897b21f70e3ca0f67bd1473c20d0100000000000000ccd77169b614a5ea498761f8f9cbee857366ae4f480ccc361a04d573cd73a8800100000000000000c44348b1d40dcfcd35f22a40245f3940c3cdfdd00fb799ab0846a93d4543478401000000000000007a347f225bddc210196a000e0a3ad53e5e7934f49f3cc533ced0091698ada2e30100000000000000ad8497c131cce1111b3df3f7b0d3ff46abacba2811bcc90485cae7291e65928701000000000000006e9b1f3209af44f3584a21f8f7ff89c38bd706e4bc708e6a8a634c72c8971017010000000000000011255f74fe3f4d80e02402df4c833ba345d4f46304c01e2ffbd8ef82c592635b010000000000000017a812a1a237a0f1cb5aab498e833941e8c0347e06cfcecf31f52da504a6dc0e01000000000000002066a905e2b83cf923dd4e90e81df1a726a62785d2c2f9d50dd2e0741e546322010000000000000099f8667078cc772cd09b4d372ca8ddc55c5235b0dccf7ad5897280ebed110d1901000000000000008fdca033dfa9af8c8502fa89698c57ed0a74f7924632ba2113f00ba797808923010000000000000016d6a5a31c8bcea0b304f49d6442e9b49925b7c09470057808977f34a5f8c2a2010000000000000040fd96ad98ee9187c7e684b53f511a504db3c3ec075b5eab6f79721cc0e9453001000000000000002d27b6dd2ea60b0a3a57a536356e7addb2cc7e4711e7bc14e2b5a68dcf4120d40100000000000000e6bd7eff04ebe623f26ee1448ed457aca7da2327cddc4ceaf8261b21bedbc536010000000000000009e2de930b9b16c1f79af987a27efeaa300483411311651a7bbd8bb27001064401000000000000009aa4faa4953519fd144db9a6ccd0009ce8c122e34e7f325e236093f60f13b5fd01000000000000000303f00bee83ef6f0b44edbb1b989f0086fafd8dc4e8230073018301f5415325010000000000000080a66399b9b029331d44b5fdc053ca2a25932340d3b6120384369a98d99b8f1a01000000000000001badde98757e591173e43a7c0704e04a48d6ca1c3d4697334d064796b74aff23010000000000000019186bf21c02f25aa88e008e033ac0dacbee89486a12526342d785accaabf6d2010000000000000024960c534cb66ef6d3d54a1ad58586b3ca3aacdf6852a2758cf1a9304c884096010000000000000069961e9695be8e4c457f4a90581eec6e3d10cfc746aac74058c4340e4004a64401000000000000007b3b0e6bbd4b9194e5929c0b6f5f80181c2bd78bb48ca237ebbcbce39a6ae74c01000000000000005be9204ada8a73c531b3f37840abfd5560b3c5c90aba388946c505628ba3b90d010000000000000053af7cd53d7e379415e0b062883c5e5b3d1bb198263091b47e86f0e70801a28b0100000000000000e523bd65b508f85a07df98946d624409b73c7a2ae9dfcd66a83de3402b5be5cd0100000000000000e95f6f082490cd77d3c2d7a4daa9670a0c2e99f53132e6ca87163891073e9f410100000000000000cb48363bec2a076bc7b17369526c008739f8278b1c863b4dd5b5dfb00bbbd0cd0100000000000000ef1508e48aa4386f1afbc63630b1f3059b316757c082aa488a97f070348b301a010000000000000052a46ea940ecb5557e7ab226d6fd9c8e67c2f6a1d540977813eafdf7246cc48e010000000000000041a5970545cd35dd4fe01ade789a2fc9d5e9252d43b1a38753f5d65c08f1f6b60100000000000000b5538ce0bcfe39809667993dc6d217ba559842267c69b1cfe9c38fc1d922dfae0100000000000000d91c49cd73f8bbb0eb32d58f46533e6aa13a128c5f994a012397de02908b0e6e0100000000000000e78237e1995da1ee60086dea342ed844969f08185254918fe9c712d895fd38690100000000000000d3023276416bc71a8e042da55efbc4219a8e126bc4440a6b85b39e6119d397720100000000000000476de9ebe5fb4c8b9f9c85018f72baf35a7544c2242b72a6603c14cdb4ec653b0100000000000000c5081c5a6799d30f15e228360ee484bb1a3bb7bbf0f6d6aebb7cc636a7ed40070100000000000000f0c6366f24c79674cf94f903b5702397ec4accbc139b904f10be3ae964d76b5d01000000000000004495bdf4e770c1247ca956a240df16e4083b47c8a589f6541a29b6fe114f0e280100000000000000f486f9a8c15b8fbc4060f5083562eb502972e6174331638bbc6c457c5f3092330100000000000000e33ba0bc68ef9cb7181293e5ba3577a1e10429eee03f94893977c627f8fd3e23010000000000000087630ce5d56d23570241a7621e3dcd5676ed56d3af452e525be17f0dae7d9ef00100000000000000ce6f160bbb770ab4bb6a5d1218222bc5048149117534e71b163f76a6ec67c05e010000000000000020faeb86a3c385b8bb27dd272fbcc71e492a4d32ad8d46d07de28b2b9f0af06201000000000000004a5c76606970b35b9ea695b09997f762fdff0776e6b2be1c99f73c07b98dd01a0100000000000000ac92506355d2851a8a4f4590d6b9e07ced1483131c85abb7c0db0aa360831ccd01000000000000002a6fec69d07344f9cfbce2e2e9fbba5112d7256c6f61776b4e3dd831c186b2640100000000000000e000b3f4df8b364f85892935409ba46855c17260ada9d4ee7dce112e315df15901000000000000008ebe9e471e20b0e6424966ab894f95886aab1144a793f4243c51fb59a7ec50c60100000000000000d88478f8eba4198935a31a70169080508826a5057f6d92163f4bff0fe2d2e50e0100000000000000cf4b7bb16ae3e3a9ed246385b9f96c7ba11684c798d701642b38e3deeb12cde001000000000000000ca5ca6de85120acc30485c8fc7f5a233ef5dd02f61bd000dc89dcfdab3bcbb5010000000000000010f4e4fa3bb9c0dc34e37fca542bdd75661d5ad3e7a7abab859a5c7459c097590100000000000000d91efed4a2507723dc6e518c33c49c234757a836de80a794e75498e7a49ce4da0100000000000000f2ad7b0956bcd0f5367539dd2d3765a57b668136ddcc03311a9443bbdb8f059f010000000000000065450e1dba914446190ba7e483f1a9b6a34ec195748f0d7a5cc7e0fa2949eadb0100000000000000f5ace480ecee6ab060373878412d4f78562a814a6e441a4cddf170d4e9de8b7901000000000000005f3e874ddb07401a776d3ee13aed51118265b350539f388881e159c9b076a70901000000000000004bd97730c47d2a63e02b80b0d44d18dcb729f57dc8591abd294d6c662f2887290100000000000000b700a2cd0f890c7c184637bf0d8acce98089d606e3ec833c7cc6d1ca807a12e6010000000000000073d39cf7d1f0be9b88353518820cc81ee0fd4c36f5be66f5d52fc18b95d313640100000000000000c8faa1c1c4686207f2411ca51a7f1d52980fc368fb67ac44fc2daed5a44e873c01000000000000003e5c24745abf7a829492ae19ac08abe9aeaa5b775054578b57095acb4cbb38290100000000000000691aac18fac02155945cac1762d371a4c874f8ce1d9cc5c75ddea665a913f7a90100000000000000ee114b6236f3d57d01798b8c4c35b94781f981155460d75f96f2f59174d336ba0100000000000000330cf27f55c99c0ea00d3f73b79118dd4fe026253e69150840f6716edbfdfa270100000000000000ea2f7258212305f0cfbb5acd88951dae4bafd1a4cf28bb4deadafbc6efe3738601000000000000008649155d06e909ee20d05f414d9dc81eb924a88d9897bd83c96997d4162a02fd01000000000000005ffdc5f8a14b94a8485f4f5c65b4e059298a36a400cc1306cbd1a929c155862201000000000000003111930061e472689f1497bfc7b5bcca1c8fc6b4e6537bef0ce5e110ff838a4101000000000000009def81a6be794e044045e70ec0076f40873a9623c735011e3028d667eeeb60be0100000000000000cb14dc67523bb5d460d658e3c25ad9bfd90898d15198974fef4013481e2c4b96010000000000000080c398def091d0d24f26b5e42454ab8744d94c6d0c25e4b3e5514b5d1c2f6504010000000000000020d4805a5ecc2cf8d9e676baec506bb8f3bae1a661a9282877d331e47991462401000000000000002a61bc914e012372c72c511edcb6febf1c419eecebaf0d55682ffddef05c54cc010000000000000084738016631f651661afb314d15ff1c3645b77548a5e2d9db78aa22e476fedc40100000000000000963039e306b0d431f3de3cbc94933cce866f9f889a20f489b3aa0fa7f692f2d90100000000000000478d27165e28650d51df6358764af1e9cb54711ad28aeb3961edc1f0a41fe5900100000000000000db00d03b8288d81733a67b1f797e7d429255ab20c418c7cde07345d651af63b401000000000000009055fd8d364c18556eccec467c8ba0e2800a9b58d5fc0cba1f991c9caee71e0601000000000000000b51ba7e01287ae7b7051c420096370f37883133533a7fe76e5878ab18f4945b010000000000000045cd6cb5cf133aeb4732a1c4338c31ca9eb60902c2899b10e93f218079277f08010000000000000029456012925d5055152c61c648f266c56a11e39d8153e14a7134cb824a51b61301000000000000005353e17f2edc6333fa533b78a33046f35e93b807a0084764836b645b33517b92010000000000000084e4d9748a54cd5bfd1deaea8db1b3e3c20b796885c90c9a07557f54f6a217f701000000000000003eaa1f104c8917d795c460b71f7fbfcd871ee89d21419392fc73e9ff03c2350101000000000000007560e2946c39f889df4b6ca4398146f4131e81836db90b83759d7d28b4e5e9930100000000000000ea342dff08fb8e0be2495a9aa252e3f2f7bac8eb56d3953c3a25e0c408813d4e010000000000000012aa8332dd6b4a1f7b464d176e73c7774ac53efefec254724c5a59c081775c04010000000000000087e9fd41bb1979d5f480c965e3616db679c2663f29aee2368f88c007d543c2b80100000000000000f4db49f9446b0bdb4db5cf8e13cdfd51a2635d50398dc00ccb86195ed50786fc0100000000000000e9699252da139514ed29a0dae73bb305c4455c261cc1a905fe120c935ed667bd01000000000000008690e680934f11e65b08ef7a07bfc0130feef51c9bfde94db9c784cc9dc9bc680100000000000000dc32c1cb869ab5b139f1f9c1eb0bddde38f84467ab380af4015f20d871253d450100000000000000d49667dc274ee2d65f621a7ed7320675aa0cca5e64d9aa0b0b0ef960e3a5e25801000000000000006d5d5d638d4e7faa7c4b0365048ce2e22482e62f017b1c28f8be60fbb0eb3c6c010000000000000077115b31ac401c567bd6342a9a2157e4b90a0b1878a2a032bd393581f58c0e6d01000000000000006f287c510fb819d5d15874d639a4a525c99a6d2ad250eecf8996848e6f3c891c0100000000000000d21221b226f8095108fef4c15b6421e23600c021d5231007149303bcd7aa38770100000000000000dd077f2303148c5571b0ad2f7ebbf383abed27706abe2f8f0bec83864d08a6c701000000000000007da7eee77620293b2b5e37d18d7d10199b2aca22d8b91e6583c32b72f0c867b901000000000000007293edcb9685271446324886855127ed08d1dc333f072368d056ea10efac90f901000000000000004f50cb97774bb9143ebe1262d58029dbab10b677703cb7ba73dc6c0fa69d20880100000000000000d6b2ba03f93a64dade1a982c548e60383f6b432585ed813256313dbf6b05afb30100000000000000266f7a94734fd29d548c0db18530c431decadcb0a805f1343d53f0a9a1a44c7a0100000000000000c1e8fae159c5c88295354eb8086199144f5b7c8d4cad3fb78d71bad645a14b3d010000000000000097e07cbb36ac8e08931387c6e8711c2334a96f05ab0dd3fb359d961669ea67fc0100000000000000d0a7b9c7846ca965e370f9d8cd9186ea3595033fe7d98427d85fc25d3881edc7010000000000000005cfa08bacb37966dd2458aeea2e9c76f3fa3985590f7aac9330a6ebd55b9c590100000000000000ac8ae2e92c2624461b7dd2cfe8d1698b09745e2dab5ac8cd21167ff70f88373b0100000000000000836ba84b9a3fa7b88449c67e9a07ab4537dd4559f54f4b3c05e0c76c739bee220100000000000000d451c22bb4b8bdc01c87e49bfc5f23e635121d666c2eec49d74979677892f2ff0100000000000000f96766ebd87138e791b416a3b45eeb1318ae801c1ce54a36ef3aa7174839a89401000000000000007ad995e784bc2c94023dd636d952af57435366edf8b9ce5c703c86605df872df01000000000000007103e1aa3471d26342b4af722b06beb74092f6af89e87c826b2283166e14f0cd010000000000000005e303fedaaac601f5810aa8908a1d883d2570de22de32751b80449cf795eb7e0100000000000000018fada1c53cf8fac7cbb0f024c9436533cf21496cf0b9c70be7c1d8dbc93a920100000000000000ba1efd6c58dc8c7624791fcf7bbf1cc2fbaeee48517a8d68a9466201d704b2520100000000000000af65a23e0e93da4675a4f20412d73a6fc9d8aca85c79dc38d57df0b123bd7bc401000000000000008abb468c1fadade8863120979456f6af5f5beb6d779e147f9a95f8b15fd0e0f801000000000000002de39966232797e98d7a65aa64a9bbe91a8bf0af7fc4bae2aa0d9262b737c27501000000000000006d897e71c0eb420268027d3387b010ca6d409090610fb9b58918aed01d3e79d501000000000000002b60d03643522eedc41974abd058defe15d63a3754a90227ef1777a2b278f8290100000000000000fb8e5024a5cd73ddb373c4efde06a36a8401b933c17fbd013afedaeea9a891210100000000000000d81cbded90c5c678ffc392409edf989a7f19162ef628f5de667fc923aee25ed80100000000000000a80a670467c1495382f3f8db089ac9e3b1fc484a8e11f8366352f353f364dc8f0100000000000000d7d64aea0432bf476aa65b35b9e85a415351c8447e2ec04e9d2ed54d3fd813c20100000000000000db12b39de455cf9106f3759db70a3d822123a8238b19e17b1206012c9e445936010000000000000029b9ac3de67bca3a14da36a63a4f2ce1f1121cfb9cd3312e181c3e6ac5b7080b0100000000000000697689b7f7d3493b484cfdd178eb56b60a810a194d2d6e38ce6f8c5f072068cf01000000000000005b43ea895d6ef9ad0e735c9d527dfb03a4e4895e93d14c6a037802e9bf5c3e9b0100000000000000ea3721c0c447496008c487b11a46b9763cd1529d76077905ddd136de7f6cf4fa0100000000000000760f1dd09855df71fc2208b63b7125df0acd1687061f35939f883ea18cee99140100000000000000224ab2a704590a84be227148b427bf0731da7d4a68873ade0ae614e0587f30ba01000000000000001219dfc6a1d99c1c4ada31f0ec4025071bcd47de94050a6314163557544be91c010000000000000042be9759370bc8d0cdd26aaa12ef2f986a99edc3c343c3e729d211ef9dcc5e5c0100000000000000621894d3a7fbca99270a379fd1b739767037082f449195f7da7dd516ffe924700100000000000000a515924233f6c57565922594435c7ea0092fad967ba3f5bb1796949385ae275201000000000000008acb451e9558b4d063ba9dc2aec6c15d436ac2702e59614ae7e6107c1ff08fd3010000000000000064d24f7e032b15b6acccdf2bf954ddba0cbf5ff2a44f447beea0333f56c18acf0100000000000000fa86c565b045b29afd23763205c738c922ee72a4337ae9a1a410a98b02bc147f01000000000000001d44e21ffb6706d8d6426ca11013980b158441e656a444d7f5095e969049c6590100000000000000465bc633035a12d987c4f78a8a3c5610e0daf7b1c2b7d5cf7e7c37f46d6cc42401000000000000002c2b43fbc7dd181e2e179828096fc0ea949cb687f99a5871a694f443d331196f0100000000000000125599d98cc0d92e1e5115169449ffcba6fd4df09ebf20f88dca38eccdb9fc870100000000000000684135b5cc845d39103b673bdc773b5a644b4a3e26d43d230916160e0b4e241f0100000000000000db126c984fcf1869f4360097ae0172c22cc0b035c7915cc81a73d708f325bcb60100000000000000320a6c7b07eb0df65fd7fde84cfd5e8c3baa94dd1ef2af07db2699c54834399101000000000000008a4940a0cc32e6d37e79e03f15bcaa48d30b9add2058659e6cfcc21b440a39dd010000000000000045d1639f0404b4b8e102e5ecfe727e9e03bddd46162087a2be282ab973d3636601000000000000006fa261826b93b721d02ed87cd0918fd579c1d5f5f397b2613345f13c728b0d3c01000000000000007802f8c67e20d2608dc4d078b69bd1aa81b487a649fa4c4c349f290e3e879320010000000000000033dfd638f662cc2dd12e417ddfab60ad22e61a94a714ad98c2bef15736482c8e0100000000000000d4a32a105c3693978edf0712a263aebf6c8fa85484465c3bef7b881998d27d9401000000000000001af91eb716396457206d08e220f4edc93ad8ad71dc4d1bf272a44a4d56f89b390100000000000000e28b354b7e2aff7171e096404d7d1afc12141bdab0780ce5df56110ba6d05d40010000000000000017aa75b292471048c91d81e6e91004301d0823f6d00140fab887540245498c860100000000000000d6bd10e1b60429a00afeb869947b3e3e96a917699979cc7415a3089fb7216d770100000000000000fcff934bdeddbcee48e3302f4399eb3adad5064f2a12423aeb6227f298526e9901000000000000005a904ad569e4eb0b3d30851f9fda7cd9e89a064b02edc4948c409b3f60873767010000000000000027ec48966d06fd56fe24232071e8985f5e391aabebd88179e190ad27a72b57e80100000000000000f8ec0e83d0aee12b5244b5af54f0b2de0b1b6867154207bf0f4b77bce1bcfd6b0100000000000000a717738aa95bc805eff85b07a4a82dd7396f810c703bb9202f01c3cd1aa62f8e0100000000000000c07ec1e7a4e4218a0ae4eda8ccbf270b424d3c31285ca43125a06d6d8593c7480100000000000000a6824bf4c4f2303d23080815d4bb514b5bd7322b1d95672276436a149e9b00760100000000000000e7bf723af78fd4b3fa6c2d35941d3374e3847ae437103c7e2f86370bdf3edcc60100000000000000be54f0bdbef1ce73269047a29d44a6cc0ec7b1936c37a3ab8d9d0a63ded45664010000000000000023cb043e91c542acf4873cbc2f568d15cc90b05bda952fc6b8d05aa31425bbc5010000000000000048af8d8ab8e00a51a692e25bede61bfeab6a1fd684ec5dd7c1f6b7135e0da3650100000000000000a586be4be691a3072076a68891f856a12de8b2f1db30febba62ebc15e9e227ff0100000000000000781e2062f8a041ab7b2063e9a8dfa9dad5e7257ec27faa23eae622304a070b760100000000000000ff10f3cb24f4ab4482666b7c50dbb1fbdfec4acfdff1fbffda61e6cf89c9a5b701000000000000006cd78bff7c7c09d1786d7f984acdf0bf775b4fb72e0a82c97e45bbbc3369293a0100000000000000032f4ee5a6809aa242e3c71cb76045e40dd384f5094df250f4d419c4f82ccb9e0100000000000000d260c1ed54d16384244da7e1827b45a5642e70c5613c889b2f4371d082416dd4010000000000000072475536df6926898b34753af3843e6ffbcbbef26efb9b63d9069efa0b0b5ae70100000000000000363221b6d6b225d60e70487b4de003bb4e7c0a9071e5b76355ba38ee8a9d488a0100000000000000c697d2f1394d7c26c80391943903966f373d6a4b460a0556fecb3f1e07336d56010000000000000056597df18e8cdf7f7c13736150232f7903209030c120ac04781f8d3367bd76d60100000000000000b9ba35ebcd0fde8732bec0303451393f8e09e43f04f1919422fbdc77c6123c630100000000000000d9462a851b447a0c0dcf852d64630ab2404426cea3eb30185c5cd40ffadbcd9f010000000000000037fde2985358b0251709ef747e528e43cab71190a8a99dd9981e1069097f41a501000000000000000738881ec154d692bd41c836d9fb135e70be9ecd2843ba1b3fe3737e09afd8d60100000000000000e2638288add77642c6836e265f43d048c5c6417d22c88b0180a354972f9360df01000000000000006eafb66f53ca23b380669cae9a047a6690f47b341dfd4edbf6d9807dc09385d8010000000000000037022cfaf5cf055bf06e3a5a269af76c229d4d3ba6f64a1cfd93c91cfe91d25e0100000000000000d2a02772d927e53b723b4059824519210ac447276a82633ca775745aae8453ae01000000000000007bafb03ab77c30427f38fc5c7579c260323ad4e5a8c33efe079fe8323827edcf0100000000000000bb66f5419fb2c9384c35c0978ff118e1b89b213f8a133d55b2e97285c4bfa5150100000000000000ef7e3e1821d3f4852df2bca228130b27a606f3f39a4356106144d2a5eaecb92e01000000000000000e8de7379963ccd7e6a801587516979accba8328d7dca5412f1d129aacaa35990100000000000000058cf43305102069403375c98ab584d88fe1e9fc7fafe97777a3f310711f56c20100000000000000d6ef0d93e7c5660c4e29753ef3463e5f653c0136929822b03d8ccc3f6ea22c960100000000000000e47b7ca9eec6d05ea740f7796e86c1408943b2bee344396260d615f75f3ec62601000000000000007d98ef81f95b58237d6f54beb70c78b278f1e2548607114ae9664d3edcf0162a0100000000000000eddf02ca9d014d3fec682f10ff5973050d2f293288bac04bfeb6f7faa482727f0100000000000000c4dffa800bc5771836e13dd7e5d1cc6088f37addb8b3b35c3c6c22319e213f310100000000000000486bfe1553dcada6dd94fbc3640e82d8b835de0ca98c96deca6a67c6ed9f303c0100000000000000bce1c5ea881c7feeb9b2c16ed44173bb274c1eb7cc9536864c876d0f4fdef28f01000000000000009fd188ebadbd3546df1771cbb6fd860d7dd8196330c755c1caf86c030b8278ed0100000000000000fd5e5a215378f64380e7c7f0a3e460ae27f6c49749238e861a56d4a3224cb94e010000000000000078b94d0ede9300255a54665e715e2f5effe5e38afff3cc241f6916a8b377c39e0100000000000000510b36800d6e8d0bbea2efaff997f800078e3ce71751c91e488a0b7ff886229e01000000000000001dd0cea06f7f1396432d12bf1acf4848f2d39bfbfee6c25987642f687f13face0100000000000000446be16437b77db51001591ce0bad92044abe126d1d3883d164247edf95729ff01000000000000006976217c3a6dce8a1aed512e735192709e301c8b06b082d6ab39631be1824fd001000000000000004176031e3789f69d511431b6566dbab291532e48f4500b510f19cca695d07f42010000000000000096df93751b1721d4e85ba0923c47263d1cf501a90d4fb3439d5468f8751a49e80100000000000000de06a24ba55c9d53edc97da174075db860fcfbee461e3a53076f5f488af378bc0100000000000000ed76803ae3f31897d0678411455349384ff078f0785c5d68df4671de8eabc7ad01000000000000003ff264cd85b3508262c7df3d5b2f96c7eba55f8f79b07f5e985713d335dc405c010000000000000062cd543e939aadaf99e072089cd0d04ae35a0490c9fd435f9bdf4418672278460100000000000000b0954e87feab093c4ee64a4fd0194178541c099612722dd0a345a1166347740101000000000000006b40eb2e588de2d65a45ed2f193b296187a882bb0fe5f48e27b2a51e56b2863b0100000000000000e5ceef448d1cc1b0d08c10cffc424f1329cb5817a8a3bdce58c6e0f58bd72ff00100000000000000f2991af2d98468bebde0fb7dc976c76fb5d654e1a0b5fb2e920dba646d5b53bf0100000000000000fced31325ed7baea9e24c7325e98f6870d071511512e2d58449110974f88187d010000000000000018d6de032e678be87d23ffa196e9cefeda24bc30a639590f53b16b0dc0f6f1c60100000000000000a77b7390c339af3c369fb8e4ae6eff3b8a22813bfeb30be3b44d5d4a2964209e0100000000000000317a02e6ea1fd1726ccec175c31e78709063920a17bfde6e88e71e63b8f1e3d6010000000000000013cee83bf04f1925f28dbf73375dd178e1f346c523f1abc3add44645fe92afe101000000000000001b79c6a6d995530a3079beb8089ed9c7509074d555d09ee609371a8f7b959f5601000000000000001c59c1f06e6794b5867a7700b75c411a45bc3c3606aba624d0c5b48c79deda5f010000000000000023ebb989af40e5507c3f3706985c99d98767ae0d939e240b388cc951bc37e2fa010000000000000038e12ef424de5168f14c1ffcce3b5eff9d15652ce9d74b0e2efb4f368fdc4f9f0100000000000000af036d81b48d6bc1a5c58f570604ee8ecee978462d3f28cb29b91aceeef240920100000000000000ed6ed02fdd62a9be7c746864bae18c26cf37106806e236f5f636bb8393333cd90100000000000000484085539bf552175583119424c3de5a0e73d31ad44c2cc96247ebb2900549fe0100000000000000ce526d9252ff809b25474e91c41f0df858535b59841bf259e3590f838c1fd41701000000000000006c73ce8c491e9cef55d95da6774cd7d49b3fe0f4b5157da2ac9ee6350e2a1f080100000000000000ffd11b5d82cb1303c72728b5611f181a9523684ca6c88dd54c1fa0ccf653922501000000000000003cdf3b732acc98ee8638081b4b954484fbd8f54e8b328fad2a4f4763fc1ff5ba0100000000000000899b18c7480d594d114e05e9b1d9bfeb96f202b11ffbb0684dce7cdc9139b93f010000000000000013d50cf56f97c6b8476a38df85f6944e864b92aa0ff12c5b2e14c4f09a4513720100000000000000b6a6d4117e0372d15ae130725cd0f021d88ba21ce272b3d3b9f249f6115507b9010000000000000045ffba9a30b859551b8e4f530a4fd67e372888fbeb6681828c37a8cdad65acac0100000000000000158a62b8453d55fb1ec781456f7417695276598ea42b1d33dc4e0717454d3827010000000000000087d730a4c86f3e247e82e73090cafe862c065339cf8a7731413c9102a0a145770100000000000000403749db81af533827c84d541d1ac778782d6109f7fb6edcaa6e4713b3297c7a0100000000000000e7b20af24874bc41aed321549fe5c48db8b473c17e901767e26578466d43790901000000000000002db20384794d6fe42a5aaecbe3471d88d55ed77f321282d2b1ead784dcc512fe0100000000000000153f77fc042ff4e076dc0e5d587ff67b887040c9662c90065f4f69968f76875f0100000000000000b1bb569b92cac0354539e6202f3163eb03b3151defb11a300ff1bf9e151b94ca010000000000000047ffbf4ed7157d9278adae9b63145091a0be667894ce83f134a599b5967039220100000000000000784634428f017ab3c54a602af370fb5d0c62d6f56698ab24589c28b235e547a80100000000000000937a3919d22a63fa2687b4428d22b5ee647c23b1d8ca5f45db9f52643133e2710100000000000000ac252bc158884d75a26c0095493b7c39e56f0b0115593556a7008e9d09080cd0010000000000000087eb19dec3eb0090b813873735bda3004b683b8f2db09d4d9565ffd4c3d765cf01000000000000008a72ff66f1f4bf88b9d455645a48fbe24626c34825bc1bbf78ea3f0794b71ea20100000000000000abdda69c627bfb86f8a70688075f6f772e899bc69ab9df438164936bcf0b74090100000000000000694a1c79c2541b621234d91e65237e2faf8a0edf76a7a32fdd6f10ee3aaf6ce40100000000000000bd15ffb5bd05c8579c29877961ec81b57fe9151461c2882b3592ef7d534402030100000000000000a2db26abf9c6eb1690acabc0b9ecb085e644eb3b3d73eac5b0f5eb077a1a93e50100000000000000653baa7ebbfafeab9ebf2e396b918df4423a5fcfb82cc2e5a1c5e4777267b89a010000000000000039b36f605369bf43b62b997aad59376b4c789534b255a138b006a8fc98730bd30100000000000000fa9ef3c70264916a69241674ea38de22fdf3e7c840784b83bc79b92ba66e69de010000000000000094c6d4303e82a501d02b675d4c9571817854206fc3183b68b720aa5b4734d32c01000000000000005721cfad729f74fe4c3cfc2c1f239cedb95282f3440eeadf95282eda480fce310100000000000000086b0d177fb2e50c1283d6a2ad68173986e10e075b7b1dcdf2373c07ad49b04001000000000000007e3f9bc4ff54793c5bd4f3e891cc2979f78c1f43d16efdf54f13056a504c647001000000000000007330dedfdb78e5fac3b1bbb4e814a31f2ff91c6c1ce84b5f393b6544c0d3fa880100000000000000d71ff8ad1d6d3ecc39033a218036e7cb4e47e73f750af6df357eacff26a80cf50100000000000000e5917a19b2f462fedf8dd61b027c818cba8130a1f93939a89133a59cd02ce6e80100000000000000b0db78ce1e3153e9c7769fe0dceef817890d018dd7c94baebee2e5d773a088260100000000000000803f2723a35e5b8f3da79909ad5449b8c71add31f40c2613fa86ffe93a0b6ad00100000000000000c3d791f47bc89d921ce1bc846a5a1b69dbf320157367149ec685f8a28974b0f40100000000000000bf190a1c957fee4e488a8c97214c82549bf428da423f0aeb7439d8ba6335ca590100000000000000dc85cadbffd17acffcf992b3571cd81bb586af35da43c4d0161382fb1f1a517901000000000000009da8b2697cde856d81397d95a5977a728f2e4f32c2eb18298512b855803ff34101000000000000005527d3061a66692f9ba901c4749efc35942f4ab06e7e023ef1e6b5d327b772ad01000000000000007de38ac12436274b769a0dc47843334a144337ca5af11de5dc12e7fff9b74ac3010000000000000069b7dd071c24e290d9f20dbbad610c02f93c6a7aa75b31a826f03e8656cb0e1c01000000000000002624e4d38f7aca132eb048a805916d28f2667f1a6c21d3e4e04517020a892862010000000000000027199763db53cabf829fe2cd060c9435eb4de7551ea2695415db060c8ce83c3d01000000000000005148a1df866027cd8e0d5b71cc12beaaec2b0e25d5973c757c100d92b3668dba0100000000000000c82a5e415125b430a2478ba0a9906248dd63fcb5a3926d89e3aef221395f65a901000000000000005e9d7de5764efd63cd638690bf5d11ec1270f353fe0d59755ae7332467c52a09010000000000000044bd6023acde766f5e0397075b5fabe87c8c97a19b2a0f3f7e5cd30b94bd8bc70100000000000000594f87b1af1313d47c398a87611ebdfa97789e0597774209133413f8aa887bd9010000000000000004f60a8b24269e2d199e03578fb2d3582dd0f805b5ae692fd26b509f162525d40100000000000000e206ebfcc7ce209d3c7379cfe5b02a9576c6230c0602136eea49a09b827a221c0100000000000000bf9baff512a84d8700d90dd9832b815d41ec85b719d537d079bf8a9cf497bdcf0100000000000000c9608853ead1366af252b5e189190127425449eb9aafe1f269fb643bdb19be500100000000000000c8caee6f6eddc41c6cc55e554343392cbc13d2a8a57b97f6f85fc965bdd20ce80100000000000000c6caeeb8f4b6c9927e8c8837424b072053258570fbb5457c995f06fd07ef1b3d010000000000000024481ad5c626eeae4e80376c141969f4a51b4e2e9b3378c78bfef725b2aa06790100000000000000d61269b83299036692bfedd83833f72f09512aaf6824c3a5236d221cf3a545940100000000000000d5fbd3738bf5478039ffacd8ea1bc79a1c7002136ad3b13fd4318fe9c4f2b8bc0100000000000000c5b4ac74f7bdf6d0df943f13a29b0eafff2f9adba59adfa570717c23cbc98a340100000000000000804199e81aa36b7e08c233913e10f8368f5de3db55fb9379ca2ec093491f84b60100000000000000e0eceb9b184b221baf024ec87ce1ae50570785c91fa126199655e94a15e412480100000000000000a7c25acf755c8586919da5fab860f79eb989d6a8caba54705e2a673747b7657c010000000000000047e463cc6cad6fc2b7f8eabcf264e3fe94c1a3f1803242ee6077a685d3a3f4e00100000000000000961b09f71cebb814989f32405d45c9e01f8c5f05387d165f727cca04882405a801000000000000001e2dc71a8cc9464b4b2ac21cf60434fae31b453bc9bedafe750b93195f231d95010000000000000003a79410a8ab53a01b41a481efcf139299c5f7b3ee03f8a05c1024e94fbff2520100000000000000ce406e4b70bccc116a28f06102a36038727a69a304a5691c97f27b659e710ca10100000000000000f4a3768adbda2999792c3ac13e8c71dd4bc9351d59aa9ccd5834868ab1a5e9530100000000000000a16a450cf63fe111b213ce68e52b7cf60f21820dcb65aa00601779a9667172230100000000000000fd0eb3ea058742391c2dca3db9c940833d0efd2f212f8b6c216e2107cedfcc140100000000000000198656a49ac2d94c1907de85e300a81d02f55a44e1822aa098db173ccace0b240100000000000000070388bc471877a38c06ba4955a559c2a2974e95e777289816076c7346744a500100000000000000adeebf525282e339b9b1f3dc2b1bf0ee1ef8ad011d56fab5d350b6cd8756579001000000000000009e1fc747890c37db6c4620e595bd4502d15056bea6c3fd8634ca4e6bea4606a6010000000000000070870ea7d23150e78cf277e2bebdcd5a81b7854d17b9c6a3a5efb8e5e366d3ea0100000000000000725861f776fd5ff4c106e1478ee0691e91f1cedb8cdb504cdb3e1b4231c115980100000000000000b6b1aae660794b9e1f1ff776b3dfd823768c7fcaf8282298f6ed9bbca40c81e50100000000000000b219e42694ea0ec1160cefce79c9017155890fb9820e2d754a1be47184092141010000000000000010198aad6972642b12890f39a8a5aa9d81bbb2b0497c78c777904a400dcf829d0100000000000000932914dc898bfdd1eb7faf003ab09a97a371f143911569f1f10aa7c1b061f88f0100000000000000d68fe09a45ccb14b7caeaa0afc1280fbd39bfa07dc3d902b0b93ac099126abc00100000000000000c6deac832f8b0d2cf50e23febc37b82bebae2f43d75fd100d08980685064935f0100000000000000dbfa2352c0e8555e9933df8d1f0f19eb18ac2ddd9915472cf648cf8be1e0f75c0100000000000000f935302e01a1400295915efdd514ed17d9bb652dbb9ff1abe735d74a8d27104b01000000000000009ea9dbe0cec823df2514f4522e6e8e700e30fa222471245368d0a1f3916fef490100000000000000ad67e8e36d0b47189e021ecd7581922066362dc4c5f2ea1f9da46ae7825284ae010000000000000070a06faee33e45829e64355dc12bbcb84f0017794ff4450aa0473da424118a51010000000000000062b5a5ee1eddc47c61fa975d10bf07031a346fe5879276a2d7b5c146dcc2b1c20100000000000000e8deb9b6c857fb01542ef25bdee8b55b4d90c4069ab003aa4f15699e253fae470100000000000000840e02cf09693432d7a2e2f426009154b83d64824fe9d5960959635e8afb1e370100000000000000ff95b0b84ad21101f39414cc188fa680b950e6b0275a547265d1913e0a882edc01000000000000006ef7d7b23620a1b8d056dccbc113bc1141d089e12a0bda2acab6162d23cea97c0100000000000000b0e79361a461c2b55d5895d3ea11d803df48909ca3c6b1f082d8a4488bc8f068010000000000000043ee65b2ac3f8cd6eaabfe784e75c9c8763bb262da6e5c89331440ab6adcba7b01000000000000006f7153b550fad407bb24c617c790390ac5e00cdb6dde02a9947983ddb2b5f395010000000000000051dc7faf613dc11c9d2ed86db230a1b119b89dacb7e50b8902be6b90f2c6d92901000000000000004155b38bb22d421d48b07f1bad1d82b68dfca2887c56aa4cb513350afdca4b4b01000000000000001ebc598b563a76fcf05a3c4fd25bc1c8496dfd44d73d01934d5a2fdc0d3f72ac0100000000000000ef7c230fbed7284e016b3c9eccad304d1e214c926763c1fc7979734b273f335401000000000000008dea3098e375a1ae6d6bf328b6291c3f3c25b6874efdbe796d78aa8971acb6a601000000000000004d30d35cc1a0c2a91a73d2b168047fd9e2339c45d4f0a96576fb258511aac3cc010000000000000073269b6e07b97fda590681638536929e2110144cf3618ee7c46fe85de37fc52c01000000000000008b930c83cff7a218141050d10f125cf6076f1ff9189a3788df840b0643a06b780100000000000000f2553eebe0dae580ff47f2ddd6739409e3a3bdd05015bf4dca15233dec1b42cf01000000000000005c3c02f412be5563e77739b8f2d824222417c18ebf4aeadfc8dec9dbbf7e2cae0100000000000000f27c568848982feeb905d72ce84db24129f074e871b6af9d9a9abe594187b4f00100000000000000caa143d9cb19ea111a3eb681f29910a05d0d517a674e8cad891b47c439acb38f01000000000000009dcbf390a9c1f74845ce4e8b4622003730ddef85da758293342a80c0892c9f14010000000000000095b085fcc40b6245daabb2fe603023b5c0d4b57a2e3273202d4f66b557f510570100000000000000b37a4373cda750c4cd9b4414f816d29638a5c2f18c00f46f4a865070131a73a0010000000000000047bf8f076eccac66229037703e5a910d2f96aa50d82b2cbe6e1763986a08111f0100000000000000c8c53762490c91aea43491f500a72843e4cc37bb0981867b50c0eb396a79242e01000000000000000899b4434b3ce0818b21838a7765ed2a71b3a5bacb7649be04feeedc4f005ad00100000000000000622a3cfc2a1a3ba6519453fb21c7de1a3435488c89d910f46dc0aa281f38ef6801000000000000008777bebefe7fcb2db8baa196332a3201ec176c68fc1301f95ef12341c320f4d90100000000000000cf152611e73f53af6abc0a235c6732391b80d20d7abbd8d2ab8de408a96b84ac0100000000000000b625674063911d011dd0ccf274bdf63c744caa9000969de4022bec4bc89db5590100000000000000e3a7997474706f3d9cce4f03f7f0373fbcb527509c18996116b5a5849622f2c10100000000000000717d015fa356c546313c535cf5d3fb5e2515836765b269d5714a51258dc1f6d501000000000000008ade77a41e0ef26e54788c6075a73b0687db325ec479198b69094c03165919a00100000000000000293f0c2b3ec0e4297e71b8101cc630dfa5161484ff20653d344d93e984cfcf1a0100000000000000445a772280570650dbe73611369ab9051c4e7dfdc458ee039c7b1e4908568b44010000000000000086957cee8be58488331b4936a0049e77464aa8ff2255d9d78ec33239cbd77e460100000000000000ac5f1503a9d06b06fbb8062584e045abbe365d65af5ff3382e2ce565760ac2ef010000000000000000000000054241424501010c3374b8e5d05fa21b01d0da59264b8204e070b1d0c36a7c5bc9af657c0b694a8aae15ee2f5a1840cfd8b007a6c9b5b0a46022e3ce4e56f57541173c1c8d7085"); -/// Authorities set id, enacted by the Kusama header #22780167. -const NEXT_AUTHORITIES_SET_ID: u64 = 8_906; - -pub struct BridgeToKusamaUnstuck; - -impl OnRuntimeUpgrade for BridgeToKusamaUnstuck { - fn on_runtime_upgrade() -> Weight { - if !is_bridge_stuck() { - return RocksDbWeight::get().reads(1); - } - - log::info!(target: LOG_TARGET, "Updating authorities set to unstuck bridge."); - CurrentAuthoritySet::::put(next_authorities()); - - RocksDbWeight::get().reads_writes(1, 1) - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - if !is_bridge_stuck() { - log::info!(target: LOG_TARGET, "Going to unstuck bridge."); - } else { - log::info!(target: LOG_TARGET, "Bridge is not stuck."); - } - Ok(vec![]) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - frame_support::ensure!(!is_bridge_stuck(), "Bridge is still stuck."); - Ok(()) - } -} - -fn is_bridge_stuck() -> bool { - // bad state is where best header is #22_780_167 and set id is not 8906 - BestFinalized::::get() - .map(|h| h.number() == KUSAMA_HEADER_NUMBER) - .unwrap_or(false) && - CurrentAuthoritySet::::get().set_id != - NEXT_AUTHORITIES_SET_ID -} - -fn header() -> bp_kusama::Header { - bp_kusama::Header::decode(&mut &KUSAMA_HEADER_22780167[..]).expect("checked by tests; qed") -} - -fn next_authorities() -> StoredAuthoritySet { - let header = header(); - StoredAuthoritySet { - set_id: NEXT_AUTHORITIES_SET_ID, - authorities: GrandpaConsensusLogReader::::find_scheduled_change( - &header.digest, - ) - .expect("is checked by tests; qed") - .next_authorities - .try_into() - .expect("checked by tests; qed"), - } -} - -#[test] -fn header_hash_matches() { - /// Hash of best Kusama header #22780167 known to Polkadot BH. - /// Source: https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc-kusama.luckyfriday.io#/explorer/query/22780167 - const KUSAMA_HEADER_HASH: [u8; 32] = - hex_literal::hex!("acee9128de412d3e134c735c34998f330145f443dab6d765e8c05044a69853a3"); - - assert_eq!(header().hash(), KUSAMA_HEADER_HASH.into()); -} - -#[test] -fn next_authorities_works() { - assert_eq!(next_authorities().set_id, NEXT_AUTHORITIES_SET_ID); -} diff --git a/system-parachains/bridge-hub-paseo/src/lib.rs b/system-parachains/bridge-hub-paseo/src/lib.rs index 0ca3bb2..a0ec280 100644 --- a/system-parachains/bridge-hub-paseo/src/lib.rs +++ b/system-parachains/bridge-hub-paseo/src/lib.rs @@ -23,29 +23,26 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod bridge_to_ethereum_config; -mod bridge_to_ethereum_unstuck; -pub mod bridge_to_kusama_config; -mod bridge_to_kusama_unstuck; mod weights; pub mod xcm_config; use bridge_hub_common::message_queue::{ - AggregateMessageOrigin, NarrowOriginToSibling, ParaIdToSibling, + AggregateMessageOrigin, NarrowOriginToSibling, ParaIdToSibling, }; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::ParaId; use snowbridge_core::{ - outbound::{Command, Fee}, - AgentId, PricingParameters, + outbound::{Command, Fee}, + AgentId, PricingParameters, }; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + create_runtime_str, generic, impl_opaque_keys, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, }; use sp_std::prelude::*; @@ -54,26 +51,26 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; use frame_support::{ - construct_runtime, - dispatch::DispatchClass, - genesis_builder_helper::{build_config, create_default_config}, - parameter_types, - traits::{ - tokens::imbalance::ResolveTo, ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, - Everything, TransformOrigin, - }, - weights::{ConstantMultiplier, Weight}, - PalletId, + construct_runtime, + dispatch::DispatchClass, + genesis_builder_helper::{build_config, create_default_config}, + parameter_types, + traits::{ + tokens::imbalance::ResolveTo, ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, + Everything, TransformOrigin, + }, + weights::{ConstantMultiplier, Weight}, + PalletId, }; use frame_system::{ - limits::{BlockLength, BlockWeights}, - EnsureRoot, + limits::{BlockLength, BlockWeights}, + EnsureRoot, }; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{MultiAddress, Perbill, Permill}; use xcm_config::{ - FellowshipLocation, GovernanceLocation, StakingPot, XcmOriginToTransactDispatchOrigin, + FellowshipLocation, GovernanceLocation, StakingPot, XcmOriginToTransactDispatchOrigin, }; #[cfg(any(feature = "std", test))] @@ -81,7 +78,7 @@ pub use sp_runtime::BuildStorage; // Polkadot imports use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; -use polkadot_runtime_constants::system_parachain::{ASSET_HUB_ID, BRIDGE_HUB_ID}; +use paseo_runtime_constants::system_parachain::{ASSET_HUB_ID, BRIDGE_HUB_ID}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -89,8 +86,8 @@ use parachains_common::{AccountId, Balance, BlockNumber, Hash, Header, Nonce, Si pub use system_parachains_constants::SLOT_DURATION; use system_parachains_constants::{ - polkadot::{consensus::*, currency::*, fee::WeightToFee}, - AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, + paseo::{consensus::*, currency::*, fee::WeightToFee}, + AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, }; // XCM Imports @@ -110,32 +107,20 @@ pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - BridgeRejectObsoleteHeadersAndMessages, - bridge_to_kusama_config::RefundBridgeHubKusamaMessages, - frame_metadata_hash_extension::CheckMetadataHash, + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, + frame_metadata_hash_extension::CheckMetadataHash, ); -bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { - RuntimeCall, AccountId, - // Grandpa - BridgeKusamaGrandpa, - // Parachains - BridgeKusamaParachains, - // Messages - BridgeKusamaMessages -} - /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +generic::UncheckedExtrinsic; parameter_types! { pub DmpQueueName: &'static str = "DmpQueue"; @@ -143,29 +128,27 @@ parameter_types! { /// Migrations to apply on runtime upgrade. pub type Migrations = ( - // unreleased - frame_support::migrations::RemovePallet, - cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, - snowbridge_pallet_system::migration::v0::InitializeOnUpgrade< - Runtime, - ConstU32, - ConstU32, - >, - bridge_to_kusama_unstuck::BridgeToKusamaUnstuck, - bridge_to_ethereum_unstuck::UnstuckSnowbridge, - pallet_collator_selection::migration::v2::MigrationToV2, - // permanent - pallet_xcm::migration::MigrateToLatestXcmVersion, + // unreleased + frame_support::migrations::RemovePallet, + cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4, + snowbridge_pallet_system::migration::v0::InitializeOnUpgrade< + Runtime, + ConstU32, + ConstU32, + >, + pallet_collator_selection::migration::v2::MigrationToV2, + // permanent + pallet_xcm::migration::MigrateToLatestXcmVersion, ); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, - Migrations, + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, + Migrations, >; impl_opaque_keys! { @@ -176,20 +159,20 @@ impl_opaque_keys! { #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("bridge-hub-polkadot"), - impl_name: create_runtime_str!("bridge-hub-polkadot"), - authoring_version: 1, - spec_version: 1_002_006, - impl_version: 0, - apis: RUNTIME_API_VERSIONS, - transaction_version: 4, - state_version: 1, + spec_name: create_runtime_str!("bridge-hub-polkadot"), + impl_name: create_runtime_str!("bridge-hub-polkadot"), + authoring_version: 1, + spec_version: 1_001_002, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 4, + state_version: 1, }; /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -220,64 +203,64 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = BlakeTwo256; - /// The block type. - type Block = Block; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type RuntimeTask = RuntimeTask; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = weights::frame_system::WeightInfo; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; - type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = ConstU32<16>; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Nonce; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The block type. + type Block = Block; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type RuntimeTask = RuntimeTask; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Runtime version. + type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = weights::frame_system::WeightInfo; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = ConstU32<16>; } impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; - type WeightInfo = weights::pallet_timestamp::WeightInfo; + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type WeightInfo = weights::pallet_timestamp::WeightInfo; } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (CollatorSelection,); } parameter_types! { @@ -285,36 +268,36 @@ parameter_types! { } impl pallet_balances::Config for Runtime { - /// The type for recording an account's balance. - type Balance = Balance; - type DustRemoval = (); - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = weights::pallet_balances::WeightInfo; - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type RuntimeFreezeReason = RuntimeFreezeReason; - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<0>; + /// The type for recording an account's balance. + type Balance = Balance; + type DustRemoval = (); + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = weights::pallet_balances::WeightInfo; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + type RuntimeHoldReason = RuntimeHoldReason; + type RuntimeFreezeReason = RuntimeFreezeReason; + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<0>; } parameter_types! { /// Relay Chain `TransactionByteFee` / 10 - pub const TransactionByteFee: Balance = system_parachains_constants::polkadot::fee::TRANSACTION_BYTE_FEE; + pub const TransactionByteFee: Balance = MILLICENTS; } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = - pallet_transaction_payment::FungibleAdapter>; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = + pallet_transaction_payment::FungibleAdapter>; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; } parameter_types! { @@ -324,62 +307,62 @@ parameter_types! { } impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; - type OutboundXcmpMessageSource = XcmpQueue; - type DmpQueue = frame_support::traits::EnqueueWithOrigin; - type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; - type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; - type ConsensusHook = ConsensusHook; - type WeightInfo = weights::cumulus_pallet_parachain_system::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); + type SelfParaId = parachain_info::Pallet; + type OutboundXcmpMessageSource = XcmpQueue; + type DmpQueue = frame_support::traits::EnqueueWithOrigin; + type ReservedDmpWeight = ReservedDmpWeight; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; + type ConsensusHook = ConsensusHook; + type WeightInfo = weights::cumulus_pallet_parachain_system::WeightInfo; } type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< - Runtime, - RELAY_CHAIN_SLOT_DURATION_MILLIS, - BLOCK_PROCESSING_VELOCITY, - UNINCLUDED_SEGMENT_CAPACITY, + Runtime, + RELAY_CHAIN_SLOT_DURATION_MILLIS, + BLOCK_PROCESSING_VELOCITY, + UNINCLUDED_SEGMENT_CAPACITY, >; impl parachain_info::Config for Runtime {} parameter_types! { /// Amount of weight that can be spent per block to service messages. This was increased - /// from 35% to 60% of the max block weight to accommodate the Ethereum beacon light client - /// extrinsics. The `force_checkpoint` and `submit` extrinsics (for submit, optionally) includes - /// the sync committee's pubkeys (512 x 48 bytes). + /// from 35% to 60% of the max block weight to accommodate the Ethereum beacon light client + /// extrinsics. The `force_checkpoint` and `submit` extrinsics (for submit, optionally) includes + /// the sync committee's pubkeys (512 x 48 bytes). pub MessageQueueServiceWeight: Weight = Perbill::from_percent(60) * RuntimeBlockWeights::get().max_block; } impl pallet_message_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::pallet_message_queue::WeightInfo; - // Use the NoopMessageProcessor exclusively for benchmarks, not for tests with the - // runtime-benchmarks feature as tests require the BridgeHubMessageRouter to process messages. - // The "test" feature flag doesn't work, hence the reliance on the "std" feature, which is - // enabled during tests. - #[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))] - type MessageProcessor = - pallet_message_queue::mock_helpers::NoopMessageProcessor; - #[cfg(not(all(not(feature = "std"), feature = "runtime-benchmarks")))] - type MessageProcessor = bridge_hub_common::BridgeHubMessageRouter< - xcm_builder::ProcessXcmMessage< - AggregateMessageOrigin, - xcm_executor::XcmExecutor, - RuntimeCall, - >, - EthereumOutboundQueue, - >; - type Size = u32; - // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: - type QueueChangeHandler = NarrowOriginToSibling; - type QueuePausedQuery = NarrowOriginToSibling; - type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; - type MaxStale = sp_core::ConstU32<8>; - type ServiceWeight = MessageQueueServiceWeight; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_message_queue::WeightInfo; + // Use the NoopMessageProcessor exclusively for benchmarks, not for tests with the + // runtime-benchmarks feature as tests require the BridgeHubMessageRouter to process messages. + // The "test" feature flag doesn't work, hence the reliance on the "std" feature, which is + // enabled during tests. + #[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))] + type MessageProcessor = + pallet_message_queue::mock_helpers::NoopMessageProcessor; + #[cfg(not(all(not(feature = "std"), feature = "runtime-benchmarks")))] + type MessageProcessor = bridge_hub_common::BridgeHubMessageRouter< + xcm_builder::ProcessXcmMessage< + AggregateMessageOrigin, + xcm_executor::XcmExecutor, + RuntimeCall, + >, + EthereumOutboundQueue, + >; + type Size = u32; + // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: + type QueueChangeHandler = NarrowOriginToSibling; + type QueuePausedQuery = NarrowOriginToSibling; + type HeapSize = sp_core::ConstU32<{ 64 * 1024 }>; + type MaxStale = sp_core::ConstU32<8>; + type ServiceWeight = MessageQueueServiceWeight; } impl cumulus_pallet_aura_ext::Config for Runtime {} @@ -396,59 +379,59 @@ parameter_types! { /// Privileged origin that represents Root or Fellows. pub type RootOrFellows = EitherOfDiverse< - EnsureRoot, - EnsureXcm>, + EnsureRoot, + EnsureXcm>, >; pub type PriceForSiblingParachainDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice< - FeeAssetId, - ToSiblingBaseDeliveryFee, - TransactionByteFee, - XcmpQueue, + FeeAssetId, + ToSiblingBaseDeliveryFee, + TransactionByteFee, + XcmpQueue, >; pub type PriceForParentDelivery = polkadot_runtime_common::xcm_sender::ExponentialPrice< - FeeAssetId, - ToParentBaseDeliveryFee, - TransactionByteFee, - ParachainSystem, + FeeAssetId, + ToParentBaseDeliveryFee, + TransactionByteFee, + ParachainSystem, >; impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ChannelInfo = ParachainSystem; - type VersionWrapper = PolkadotXcm; - // Enqueue XCMP messages from siblings for later processing. - type XcmpQueue = TransformOrigin; - type MaxInboundSuspended = sp_core::ConstU32<1_000>; - type ControllerOrigin = RootOrFellows; - type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; - type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; + type RuntimeEvent = RuntimeEvent; + type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + // Enqueue XCMP messages from siblings for later processing. + type XcmpQueue = TransformOrigin; + type MaxInboundSuspended = sp_core::ConstU32<1_000>; + type ControllerOrigin = RootOrFellows; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; + type PriceForSiblingDelivery = PriceForSiblingParachainDelivery; } pub const PERIOD: u32 = 6 * HOURS; pub const OFFSET: u32 = 0; impl pallet_session::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ValidatorId = ::AccountId; - // we don't have stash and controller, thus we don't need the convert as well. - type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ShouldEndSession = pallet_session::PeriodicSessions, ConstU32>; - type NextSessionRotation = pallet_session::PeriodicSessions, ConstU32>; - type SessionManager = CollatorSelection; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; - type WeightInfo = weights::pallet_session::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type ValidatorId = ::AccountId; + // we don't have stash and controller, thus we don't need the convert as well. + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ShouldEndSession = pallet_session::PeriodicSessions, ConstU32>; + type NextSessionRotation = pallet_session::PeriodicSessions, ConstU32>; + type SessionManager = CollatorSelection; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; + type WeightInfo = weights::pallet_session::WeightInfo; } impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = ConstU32<100_000>; - type AllowMultipleBlocksPerSlot = ConstBool; - type SlotDuration = ConstU64; + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<100_000>; + type AllowMultipleBlocksPerSlot = ConstBool; + type SlotDuration = ConstU64; } parameter_types! { @@ -460,24 +443,24 @@ parameter_types! { /// We allow root, the StakingAdmin to execute privileged collator selection operations. pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< - EnsureRoot, - EnsureXcm>, + EnsureRoot, + EnsureXcm>, >; impl pallet_collator_selection::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type UpdateOrigin = CollatorSelectionUpdateOrigin; - type PotId = PotId; - type MaxCandidates = ConstU32<100>; - type MinEligibleCollators = ConstU32<4>; - type MaxInvulnerables = ConstU32<20>; - // should be a multiple of session or things will get inconsistent - type KickThreshold = ConstU32; - type ValidatorId = ::AccountId; - type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ValidatorRegistration = Session; - type WeightInfo = weights::pallet_collator_selection::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type PotId = PotId; + type MaxCandidates = ConstU32<100>; + type MinEligibleCollators = ConstU32<4>; + type MaxInvulnerables = ConstU32<20>; + // should be a multiple of session or things will get inconsistent + type KickThreshold = ConstU32; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = weights::pallet_collator_selection::WeightInfo; } parameter_types! { @@ -488,20 +471,20 @@ parameter_types! { } impl pallet_multisig::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type Currency = Balances; - type DepositBase = DepositBase; - type DepositFactor = DepositFactor; - type MaxSignatories = ConstU32<100>; - type WeightInfo = weights::pallet_multisig::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = ConstU32<100>; + type WeightInfo = weights::pallet_multisig::WeightInfo; } impl pallet_utility::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type PalletsOrigin = OriginCaller; - type WeightInfo = weights::pallet_utility::WeightInfo; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = weights::pallet_utility::WeightInfo; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -535,15 +518,6 @@ construct_runtime!( Utility: pallet_utility = 40, Multisig: pallet_multisig = 41, - // Pallets that may be used by all bridges. - BridgeRelayers: pallet_bridge_relayers = 50, - - // Kusama bridge pallets. - BridgeKusamaGrandpa: pallet_bridge_grandpa:: = 51, - BridgeKusamaParachains: pallet_bridge_parachains:: = 52, - BridgeKusamaMessages: pallet_bridge_messages:: = 53, - XcmOverBridgeHubKusama: pallet_xcm_bridge_hub:: = 54, - // Ethereum bridge pallets. EthereumInboundQueue: snowbridge_pallet_inbound_queue = 80, EthereumOutboundQueue: snowbridge_pallet_outbound_queue = 81, @@ -558,7 +532,7 @@ construct_runtime!( #[cfg(feature = "runtime-benchmarks")] mod benches { - frame_benchmarking::define_benchmarks!( + frame_benchmarking::define_benchmarks!( [frame_system, SystemBench::] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] @@ -574,12 +548,6 @@ mod benches { // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] - // Shared bridge pallets - [pallet_bridge_relayers, BridgeRelayersBench::] - // Polkadot bridge pallets. - [pallet_bridge_grandpa, KusamaFinality] - [pallet_bridge_parachains, KusamaParachains] - [pallet_bridge_messages, KusamaMessages] // Ethereum Bridge [snowbridge_pallet_inbound_queue, EthereumInboundQueue] [snowbridge_pallet_outbound_queue, EthereumOutboundQueue] @@ -751,50 +719,6 @@ impl_runtime_apis! { } } - impl bp_kusama::KusamaFinalityApi for Runtime { - fn best_finalized() -> Option> { - BridgeKusamaGrandpa::best_finalized() - } - - fn synced_headers_grandpa_info( - ) -> Vec> { - BridgeKusamaGrandpa::synced_headers_grandpa_info() - } - } - - impl bp_bridge_hub_kusama::BridgeHubKusamaFinalityApi for Runtime { - fn best_finalized() -> Option> { - BridgeKusamaParachains::best_parachain_head_id::< - bp_bridge_hub_kusama::BridgeHubKusama - >().unwrap_or(None) - } - } - - impl bp_bridge_hub_kusama::FromBridgeHubKusamaInboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, - ) -> Vec { - bridge_runtime_common::messages_api::inbound_message_details::< - Runtime, - bridge_to_kusama_config::WithBridgeHubKusamaMessagesInstance, - >(lane, messages) - } - } - - impl bp_bridge_hub_kusama::ToBridgeHubKusamaOutboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - begin: bp_messages::MessageNonce, - end: bp_messages::MessageNonce, - ) -> Vec { - bridge_runtime_common::messages_api::outbound_message_details::< - Runtime, - bridge_to_kusama_config::WithBridgeHubKusamaMessagesInstance, - >(lane, begin, end) - } - } - impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi for Runtime { fn prove_message(leaf_index: u64) -> Option { snowbridge_pallet_outbound_queue::api::prove_message::(leaf_index) @@ -848,11 +772,6 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; - use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; - type KusamaFinality = BridgeKusamaGrandpa; - type KusamaParachains = pallet_bridge_parachains::benchmarking::Pallet::; - type KusamaMessages = pallet_bridge_messages::benchmarking::Pallet::; - let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -1028,7 +947,7 @@ impl_runtime_apis! { Err(BenchmarkError::Skip) } - fn export_message_origin_and_destination( + /*fn export_message_origin_and_destination( ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> { // save XCM version for remote bridge hub let _ = PolkadotXcm::force_xcm_version( @@ -1052,7 +971,7 @@ impl_runtime_apis! { Parachain(bridge_to_kusama_config::AssetHubKusamaParaId::get().into()).into() ) ) - } + }*/ fn alias_origin() -> Result<(Location, Location), BenchmarkError> { Err(BenchmarkError::Skip) @@ -1062,114 +981,6 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; - type KusamaFinality = BridgeKusamaGrandpa; - type KusamaParachains = pallet_bridge_parachains::benchmarking::Pallet::; - type KusamaMessages = pallet_bridge_messages::benchmarking::Pallet::; - - use pallet_bridge_relayers::benchmarking::{ - Pallet as BridgeRelayersBench, - Config as BridgeRelayersConfig, - }; - - impl BridgeRelayersConfig for Runtime { - fn prepare_rewards_account( - account_params: bp_relayers::RewardsAccountParams, - reward: Balance, - ) { - let rewards_account = bp_relayers::PayRewardFromAccount::< - Balances, - AccountId - >::rewards_account(account_params); - Self::deposit_account(rewards_account, reward); - } - - fn deposit_account(account: AccountId, balance: Balance) { - use frame_support::traits::fungible::Mutate; - Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); - } - } - - use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof; - use pallet_bridge_parachains::benchmarking::Config as BridgeParachainsConfig; - - impl BridgeParachainsConfig for Runtime { - fn parachains() -> Vec { - use bp_runtime::Parachain; - vec![bp_polkadot_core::parachains::ParaId(bp_bridge_hub_kusama::BridgeHubKusama::PARACHAIN_ID)] - } - - fn prepare_parachain_heads_proof( - parachains: &[bp_polkadot_core::parachains::ParaId], - parachain_head_size: u32, - proof_size: bp_runtime::StorageProofSize, - ) -> ( - pallet_bridge_parachains::RelayBlockNumber, - pallet_bridge_parachains::RelayBlockHash, - bp_polkadot_core::parachains::ParaHeadsProof, - Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, - ) { - prepare_parachain_heads_proof::( - parachains, - parachain_head_size, - proof_size, - ) - } - } - - use bridge_runtime_common::messages_benchmarking::{ - prepare_message_delivery_proof_from_parachain, - prepare_message_proof_from_parachain, - generate_xcm_builder_bridge_message_sample, - }; - use pallet_bridge_messages::benchmarking::{ - Config as BridgeMessagesConfig, - MessageDeliveryProofParams, - MessageProofParams, - }; - - impl BridgeMessagesConfig for Runtime { - fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - let bench_lane_id = >::bench_lane_id(); - let bridged_chain_id = bridge_to_kusama_config::BridgeHubKusamaChainId::get(); - pallet_bridge_relayers::Pallet::::relayer_reward( - relayer, - bp_relayers::RewardsAccountParams::new( - bench_lane_id, - bridged_chain_id, - bp_relayers::RewardsAccountOwner::BridgedChain - ) - ).is_some() - } - - fn prepare_message_proof( - params: MessageProofParams, - ) -> (bridge_to_kusama_config::FromKusamaBridgeHubMessagesProof, Weight) { - use cumulus_primitives_core::XcmpMessageSource; - assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); - ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into()); - prepare_message_proof_from_parachain::< - Runtime, - bridge_to_kusama_config::BridgeGrandpaKusamaInstance, - bridge_to_kusama_config::WithBridgeHubKusamaMessageBridge, - >(params, generate_xcm_builder_bridge_message_sample([GlobalConsensus(Polkadot), Parachain(42)].into())) - } - - fn prepare_message_delivery_proof( - params: MessageDeliveryProofParams, - ) -> bridge_to_kusama_config::ToKusamaBridgeHubMessagesDeliveryProof { - prepare_message_delivery_proof_from_parachain::< - Runtime, - bridge_to_kusama_config::BridgeGrandpaKusamaInstance, - bridge_to_kusama_config::WithBridgeHubKusamaMessageBridge, - >(params) - } - - fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool { - use cumulus_primitives_core::XcmpMessageSource; - !XcmpQueue::take_outbound_messages(usize::MAX).is_empty() - } - } - let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -1199,12 +1010,12 @@ cumulus_pallet_parachain_system::register_validate_block! { #[cfg(test)] mod tests { - use super::*; - - #[test] - fn test_transasction_byte_fee_is_one_tenth_of_relay() { - let relay_tbf = polkadot_runtime_constants::fee::TRANSACTION_BYTE_FEE; - let parachain_tbf = TransactionByteFee::get(); - assert_eq!(relay_tbf / 10, parachain_tbf); - } + use super::*; + + #[test] + fn test_transasction_byte_fee_is_one_tenth_of_relay() { + let relay_tbf = paseo_runtime_constants::fee::TRANSACTION_BYTE_FEE; + let parachain_tbf = TransactionByteFee::get(); + assert_eq!(relay_tbf / 10, parachain_tbf); + } } diff --git a/system-parachains/bridge-hub-paseo/src/weights/block_weights.rs b/system-parachains/bridge-hub-paseo/src/weights/block_weights.rs index e7fdb2a..c2824b5 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/block_weights.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/block_weights.rs @@ -24,7 +24,7 @@ pub mod constants { parameter_types! { /// Importing a block with 0 Extrinsics. pub const BlockExecutionWeight: Weight = - Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0); + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(10_000_000), 0); } #[cfg(test)] diff --git a/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_parachain_system.rs b/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_parachain_system.rs index 1f18d8a..8c831bc 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_parachain_system.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_parachain_system.rs @@ -19,20 +19,20 @@ //! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./asset-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=./asset-hub-polkadot-chain-spec.json // --steps=50 // --repeat=20 // --pallet=cumulus_pallet_parachain_system // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./asset-hub-polkadot-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -46,28 +46,28 @@ use core::marker::PhantomData; /// Weight functions for `cumulus_pallet_parachain_system`. pub struct WeightInfo(PhantomData); impl cumulus_pallet_parachain_system::WeightInfo for WeightInfo { - /// Storage: `ParachainSystem::LastDmqMqcHead` (r:1 w:1) - /// Proof: `ParachainSystem::LastDmqMqcHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) - /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) - /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) - /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`) - /// Storage: `ParachainSystem::ProcessedDownwardMessages` (r:0 w:1) - /// Proof: `ParachainSystem::ProcessedDownwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `MessageQueue::Pages` (r:0 w:1000) - /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65585), added: 68060, mode: `MaxEncodedLen`) - /// The range of component `n` is `[0, 1000]`. - fn enqueue_inbound_downward_messages(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `49` - // Estimated: `3517` - // Minimum execution time: 2_140_000 picoseconds. - Weight::from_parts(2_185_000, 0) - .saturating_add(Weight::from_parts(0, 3517)) - // Standard Error: 21_644 - .saturating_add(Weight::from_parts(197_577_584, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(4)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - } + /// Storage: `ParachainSystem::LastDmqMqcHead` (r:1 w:1) + /// Proof: `ParachainSystem::LastDmqMqcHead` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::BookStateFor` (r:1 w:1) + /// Proof: `MessageQueue::BookStateFor` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `MessageQueue::ServiceHead` (r:1 w:1) + /// Proof: `MessageQueue::ServiceHead` (`max_values`: Some(1), `max_size`: Some(5), added: 500, mode: `MaxEncodedLen`) + /// Storage: `ParachainSystem::ProcessedDownwardMessages` (r:0 w:1) + /// Proof: `ParachainSystem::ProcessedDownwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `MessageQueue::Pages` (r:0 w:1000) + /// Proof: `MessageQueue::Pages` (`max_values`: None, `max_size`: Some(65585), added: 68060, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn enqueue_inbound_downward_messages(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `12` + // Estimated: `3517` + // Minimum execution time: 1_633_000 picoseconds. + Weight::from_parts(1_694_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + // Standard Error: 39_295 + .saturating_add(Weight::from_parts(195_057_429, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + } } diff --git a/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_xcmp_queue.rs b/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_xcmp_queue.rs index fde7ce5..5e9ed62 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_xcmp_queue.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/cumulus_pallet_xcmp_queue.rs @@ -19,20 +19,20 @@ //! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./asset-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=./asset-hub-polkadot-chain-spec.json // --steps=50 // --repeat=20 // --pallet=cumulus_pallet_xcmp_queue // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./asset-hub-polkadot-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -52,8 +52,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `76` // Estimated: `1561` - // Minimum execution time: 3_732_000 picoseconds. - Weight::from_parts(3_909_000, 0) + // Minimum execution time: 4_667_000 picoseconds. + Weight::from_parts(4_869_000, 0) .saturating_add(Weight::from_parts(0, 1561)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -72,8 +72,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `82` // Estimated: `3517` - // Minimum execution time: 9_834_000 picoseconds. - Weight::from_parts(10_241_000, 0) + // Minimum execution time: 10_920_000 picoseconds. + Weight::from_parts(11_192_000, 0) .saturating_add(Weight::from_parts(0, 3517)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -84,8 +84,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `76` // Estimated: `1561` - // Minimum execution time: 2_291_000 picoseconds. - Weight::from_parts(2_400_000, 0) + // Minimum execution time: 3_175_000 picoseconds. + Weight::from_parts(3_367_000, 0) .saturating_add(Weight::from_parts(0, 1561)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -96,8 +96,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `111` // Estimated: `1596` - // Minimum execution time: 3_158_000 picoseconds. - Weight::from_parts(3_394_000, 0) + // Minimum execution time: 4_046_000 picoseconds. + Weight::from_parts(4_365_000, 0) .saturating_add(Weight::from_parts(0, 1596)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -106,8 +106,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_037_000 picoseconds. - Weight::from_parts(6_277_000, 0) + // Minimum execution time: 6_046_000 picoseconds. + Weight::from_parts(6_273_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: UNKNOWN KEY `0x7b3237373ffdfeb1cab4222e3b520d6b345d8e88afa015075c945637c07e8f20` (r:1 w:1) @@ -128,8 +128,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `65711` // Estimated: `69176` - // Minimum execution time: 114_520_000 picoseconds. - Weight::from_parts(115_984_000, 0) + // Minimum execution time: 112_973_000 picoseconds. + Weight::from_parts(114_995_000, 0) .saturating_add(Weight::from_parts(0, 69176)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) @@ -142,8 +142,8 @@ impl cumulus_pallet_xcmp_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `65710` // Estimated: `69175` - // Minimum execution time: 52_150_000 picoseconds. - Weight::from_parts(53_802_000, 0) + // Minimum execution time: 49_829_000 picoseconds. + Weight::from_parts(51_599_000, 0) .saturating_add(Weight::from_parts(0, 69175)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) diff --git a/system-parachains/bridge-hub-paseo/src/weights/extrinsic_weights.rs b/system-parachains/bridge-hub-paseo/src/weights/extrinsic_weights.rs index 1a4adb9..10c7bbf 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/extrinsic_weights.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/extrinsic_weights.rs @@ -24,7 +24,7 @@ pub mod constants { parameter_types! { /// Executing a NO-OP `System::remarks` Extrinsic. pub const ExtrinsicBaseWeight: Weight = - Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0); + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(250_000), 0); } #[cfg(test)] diff --git a/system-parachains/bridge-hub-paseo/src/weights/frame_system.rs b/system-parachains/bridge-hub-paseo/src/weights/frame_system.rs index 7dc3031..3093908 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/frame_system.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/frame_system.rs @@ -19,20 +19,20 @@ //! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./asset-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=./asset-hub-polkadot-chain-spec.json // --steps=50 // --repeat=20 // --pallet=frame_system // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./asset-hub-polkadot-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -51,22 +51,22 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_582_000 picoseconds. - Weight::from_parts(1_665_000, 0) + // Minimum execution time: 1_547_000 picoseconds. + Weight::from_parts(737_907, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(389, 0).saturating_mul(b.into())) + .saturating_add(Weight::from_parts(387, 0).saturating_mul(b.into())) } /// The range of component `b` is `[0, 3932160]`. fn remark_with_event(b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_627_000 picoseconds. - Weight::from_parts(4_783_000, 0) + // Minimum execution time: 4_705_000 picoseconds. + Weight::from_parts(64_855_385, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_803, 0).saturating_mul(b.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_632, 0).saturating_mul(b.into())) } /// Storage: `System::Digest` (r:1 w:1) /// Proof: `System::Digest` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -76,8 +76,8 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1485` - // Minimum execution time: 2_856_000 picoseconds. - Weight::from_parts(3_097_000, 0) + // Minimum execution time: 2_934_000 picoseconds. + Weight::from_parts(3_157_000, 0) .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -96,11 +96,11 @@ impl frame_system::WeightInfo for WeightInfo { /// Proof: `ParachainSystem::DidSetValidationCode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `165` - // Estimated: `1650` - // Minimum execution time: 103_204_469_000 picoseconds. - Weight::from_parts(106_838_413_000, 0) - .saturating_add(Weight::from_parts(0, 1650)) + // Measured: `127` + // Estimated: `1612` + // Minimum execution time: 94_596_353_000 picoseconds. + Weight::from_parts(98_551_357_000, 0) + .saturating_add(Weight::from_parts(0, 1612)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -111,11 +111,11 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_619_000 picoseconds. - Weight::from_parts(1_672_000, 0) + // Minimum execution time: 1_616_000 picoseconds. + Weight::from_parts(1_721_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2_464 - .saturating_add(Weight::from_parts(760_804, 0).saturating_mul(i.into())) + // Standard Error: 1_834 + .saturating_add(Weight::from_parts(726_484, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -125,11 +125,11 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_570_000 picoseconds. - Weight::from_parts(1_665_000, 0) + // Minimum execution time: 1_580_000 picoseconds. + Weight::from_parts(1_666_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1_141 - .saturating_add(Weight::from_parts(566_279, 0).saturating_mul(i.into())) + // Standard Error: 883 + .saturating_add(Weight::from_parts(546_438, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -137,13 +137,13 @@ impl frame_system::WeightInfo for WeightInfo { /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `67 + p * (69 ±0)` - // Estimated: `73 + p * (70 ±0)` - // Minimum execution time: 3_205_000 picoseconds. - Weight::from_parts(3_365_000, 0) - .saturating_add(Weight::from_parts(0, 73)) - // Standard Error: 2_155 - .saturating_add(Weight::from_parts(1_185_589, 0).saturating_mul(p.into())) + // Measured: `80 + p * (69 ±0)` + // Estimated: `80 + p * (70 ±0)` + // Minimum execution time: 3_243_000 picoseconds. + Weight::from_parts(3_430_000, 0) + .saturating_add(Weight::from_parts(0, 80)) + // Standard Error: 1_513 + .saturating_add(Weight::from_parts(1_137_698, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) .saturating_add(Weight::from_parts(0, 70).saturating_mul(p.into())) @@ -154,8 +154,8 @@ impl frame_system::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 15_605_000 picoseconds. - Weight::from_parts(17_404_000, 0) + // Minimum execution time: 8_295_000 picoseconds. + Weight::from_parts(9_008_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -175,11 +175,11 @@ impl frame_system::WeightInfo for WeightInfo { /// Proof: `ParachainSystem::DidSetValidationCode` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn apply_authorized_upgrade() -> Weight { // Proof Size summary in bytes: - // Measured: `187` - // Estimated: `1672` - // Minimum execution time: 107_348_957_000 picoseconds. - Weight::from_parts(110_261_219_000, 0) - .saturating_add(Weight::from_parts(0, 1672)) + // Measured: `149` + // Estimated: `1634` + // Minimum execution time: 99_450_713_000 picoseconds. + Weight::from_parts(102_008_052_000, 0) + .saturating_add(Weight::from_parts(0, 1634)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } diff --git a/system-parachains/bridge-hub-paseo/src/weights/mod.rs b/system-parachains/bridge-hub-paseo/src/weights/mod.rs index a1871c2..e096a70 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/mod.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/mod.rs @@ -17,22 +17,12 @@ //! Expose the auto generated weight files. -use crate::Runtime; -use ::pallet_bridge_messages::WeightInfoExt as MessagesWeightInfoExt; -use ::pallet_bridge_parachains::WeightInfoExt as ParachainsWeightInfoExt; -use ::pallet_bridge_relayers::WeightInfoExt as _; -use frame_support::weights::Weight; - pub mod block_weights; pub mod cumulus_pallet_parachain_system; pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_balances; -pub mod pallet_bridge_grandpa; -pub mod pallet_bridge_messages; -pub mod pallet_bridge_parachains; -pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_message_queue; pub mod pallet_multisig; @@ -51,24 +41,3 @@ pub mod xcm; pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use rocksdb_weights::constants::RocksDbWeight; - -impl MessagesWeightInfoExt for pallet_bridge_messages::WeightInfo { - fn expected_extra_storage_proof_size() -> u32 { - bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE - } - - fn receive_messages_proof_overhead_from_runtime() -> Weight { - pallet_bridge_relayers::WeightInfo::::receive_messages_proof_overhead_from_runtime( - ) - } - - fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { - pallet_bridge_relayers::WeightInfo::::receive_messages_delivery_proof_overhead_from_runtime() - } -} - -impl ParachainsWeightInfoExt for pallet_bridge_parachains::WeightInfo { - fn expected_extra_storage_proof_size() -> u32 { - bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE - } -} diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_balances.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_balances.rs index 5498809..655a620 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_balances.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/pallet_balances.rs @@ -19,20 +19,20 @@ //! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./asset-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=./asset-hub-polkadot-chain-spec.json // --steps=50 // --repeat=20 // --pallet=pallet_balances // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./asset-hub-polkadot-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -52,8 +52,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 43_393_000 picoseconds. - Weight::from_parts(45_025_000, 0) + // Minimum execution time: 42_117_000 picoseconds. + Weight::from_parts(42_963_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -64,8 +64,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 34_858_000 picoseconds. - Weight::from_parts(35_951_000, 0) + // Minimum execution time: 33_016_000 picoseconds. + Weight::from_parts(33_442_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -76,8 +76,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 12_526_000 picoseconds. - Weight::from_parts(12_906_000, 0) + // Minimum execution time: 13_333_000 picoseconds. + Weight::from_parts(14_248_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -88,8 +88,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 17_279_000 picoseconds. - Weight::from_parts(17_652_000, 0) + // Minimum execution time: 18_120_000 picoseconds. + Weight::from_parts(18_752_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -100,8 +100,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `103` // Estimated: `6196` - // Minimum execution time: 45_702_000 picoseconds. - Weight::from_parts(46_632_000, 0) + // Minimum execution time: 45_143_000 picoseconds. + Weight::from_parts(46_230_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -112,8 +112,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3593` - // Minimum execution time: 43_725_000 picoseconds. - Weight::from_parts(44_663_000, 0) + // Minimum execution time: 41_179_000 picoseconds. + Weight::from_parts(42_016_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -124,8 +124,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `174` // Estimated: `3593` - // Minimum execution time: 15_261_000 picoseconds. - Weight::from_parts(15_780_000, 0) + // Minimum execution time: 15_844_000 picoseconds. + Weight::from_parts(16_408_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -137,11 +137,11 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + u * (136 ±0)` // Estimated: `990 + u * (2603 ±0)` - // Minimum execution time: 14_617_000 picoseconds. - Weight::from_parts(14_952_000, 0) + // Minimum execution time: 15_004_000 picoseconds. + Weight::from_parts(15_351_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 16_825 - .saturating_add(Weight::from_parts(13_796_847, 0).saturating_mul(u.into())) + // Standard Error: 11_567 + .saturating_add(Weight::from_parts(13_035_118, 0).saturating_mul(u.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(u.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(u.into()))) .saturating_add(Weight::from_parts(0, 2603).saturating_mul(u.into())) @@ -152,8 +152,8 @@ impl pallet_balances::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `1501` - // Minimum execution time: 4_962_000 picoseconds. - Weight::from_parts(5_234_000, 0) + // Minimum execution time: 5_221_000 picoseconds. + Weight::from_parts(5_622_000, 0) .saturating_add(Weight::from_parts(0, 1501)) .saturating_add(T::DbWeight::get().reads(1)) } diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_grandpa.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_grandpa.rs deleted file mode 100644 index b0c2d02..0000000 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_grandpa.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md -// for a list of specific contributors. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//! Autogenerated weights for `pallet_bridge_grandpa` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=./bridge-hub-polkadot-chain-spec.json -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_grandpa -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ -// --header=./file_header.txt - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_bridge_grandpa`. -pub struct WeightInfo(PhantomData); -impl pallet_bridge_grandpa::WeightInfo for WeightInfo { - /// Storage: `BridgeKusamaGrandpa::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaGrandpa::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::BestFinalized` (r:1 w:1) - /// Proof: `BridgeKusamaGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::CurrentAuthoritySet` (r:1 w:0) - /// Proof: `BridgeKusamaGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::ImportedHashesPointer` (r:1 w:1) - /// Proof: `BridgeKusamaGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::ImportedHashes` (r:1 w:1) - /// Proof: `BridgeKusamaGrandpa::ImportedHashes` (`max_values`: Some(1200), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::ImportedHeaders` (r:0 w:2) - /// Proof: `BridgeKusamaGrandpa::ImportedHeaders` (`max_values`: Some(1200), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) - /// The range of component `p` is `[1, 838]`. - /// The range of component `v` is `[50, 100]`. - fn submit_finality_proof(p: u32, v: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `302 + p * (60 ±0)` - // Estimated: `51735` - // Minimum execution time: 304_219_000 picoseconds. - Weight::from_parts(38_797_291, 0) - .saturating_add(Weight::from_parts(0, 51735)) - // Standard Error: 5_837 - .saturating_add(Weight::from_parts(55_270_177, 0).saturating_mul(p.into())) - // Standard Error: 97_366 - .saturating_add(Weight::from_parts(2_496_036, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(5)) - } -} diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_messages.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_messages.rs deleted file mode 100644 index 1246e47..0000000 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_messages.rs +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md -// for a list of specific contributors. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//! Autogenerated weights for `pallet_bridge_messages` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=./bridge-hub-polkadot-chain-spec.json -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_messages -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ -// --header=./file_header.txt - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_bridge_messages`. -pub struct WeightInfo(PhantomData); -impl pallet_bridge_messages::WeightInfo for WeightInfo { - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) - /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::InboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn receive_single_message_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `562` - // Estimated: `52645` - // Minimum execution time: 39_459_000 picoseconds. - Weight::from_parts(41_009_000, 0) - .saturating_add(Weight::from_parts(0, 52645)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) - /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::InboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn receive_two_messages_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `562` - // Estimated: `52645` - // Minimum execution time: 50_372_000 picoseconds. - Weight::from_parts(51_775_000, 0) - .saturating_add(Weight::from_parts(0, 52645)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) - /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::InboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - // Proof Size summary in bytes: - // Measured: `562` - // Estimated: `52645` - // Minimum execution time: 44_166_000 picoseconds. - Weight::from_parts(45_680_000, 0) - .saturating_add(Weight::from_parts(0, 52645)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) - /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::InboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) - fn receive_single_message_proof_1_kb() -> Weight { - // Proof Size summary in bytes: - // Measured: `530` - // Estimated: `52645` - // Minimum execution time: 38_320_000 picoseconds. - Weight::from_parts(39_403_000, 0) - .saturating_add(Weight::from_parts(0, 52645)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) - /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::InboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) - fn receive_single_message_proof_16_kb() -> Weight { - // Proof Size summary in bytes: - // Measured: `530` - // Estimated: `52645` - // Minimum execution time: 69_386_000 picoseconds. - Weight::from_parts(72_218_000, 0) - .saturating_add(Weight::from_parts(0, 52645)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::OutboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::OutboundLanes` (`max_values`: Some(1), `max_size`: Some(44), added: 539, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) - /// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1) - /// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn receive_delivery_proof_for_single_message() -> Weight { - // Proof Size summary in bytes: - // Measured: `432` - // Estimated: `3897` - // Minimum execution time: 32_734_000 picoseconds. - Weight::from_parts(33_370_000, 0) - .saturating_add(Weight::from_parts(0, 3897)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::OutboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::OutboundLanes` (`max_values`: Some(1), `max_size`: Some(44), added: 539, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) - /// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1) - /// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - // Proof Size summary in bytes: - // Measured: `432` - // Estimated: `3897` - // Minimum execution time: 32_343_000 picoseconds. - Weight::from_parts(33_614_000, 0) - .saturating_add(Weight::from_parts(0, 3897)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::OutboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::OutboundLanes` (`max_values`: Some(1), `max_size`: Some(44), added: 539, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) - /// Storage: `BridgeRelayers::RelayerRewards` (r:2 w:2) - /// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - // Proof Size summary in bytes: - // Measured: `432` - // Estimated: `6086` - // Minimum execution time: 37_146_000 picoseconds. - Weight::from_parts(38_228_000, 0) - .saturating_add(Weight::from_parts(0, 6086)) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) - /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::InboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0) - /// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) - /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) - /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `i` is `[128, 2048]`. - fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `731` - // Estimated: `52645` - // Minimum execution time: 62_066_000 picoseconds. - Weight::from_parts(63_215_134, 0) - .saturating_add(Weight::from_parts(0, 52645)) - // Standard Error: 84 - .saturating_add(Weight::from_parts(9_324, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(10)) - .saturating_add(T::DbWeight::get().writes(4)) - } -} diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_parachains.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_parachains.rs deleted file mode 100644 index ded28f3..0000000 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_parachains.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md -// for a list of specific contributors. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//! Autogenerated weights for `pallet_bridge_parachains` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=./bridge-hub-polkadot-chain-spec.json -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_parachains -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ -// --header=./file_header.txt - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_bridge_parachains`. -pub struct WeightInfo(PhantomData); -impl pallet_bridge_parachains::WeightInfo for WeightInfo { - /// Storage: `BridgeKusamaParachains::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::ImportedHeaders` (r:1 w:0) - /// Proof: `BridgeKusamaGrandpa::ImportedHeaders` (`max_values`: Some(1200), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ParasInfo` (r:1 w:1) - /// Proof: `BridgeKusamaParachains::ParasInfo` (`max_values`: Some(1), `max_size`: Some(60), added: 555, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHashes` (r:1 w:1) - /// Proof: `BridgeKusamaParachains::ImportedParaHashes` (`max_values`: Some(600), `max_size`: Some(64), added: 1549, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:0 w:1) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - /// The range of component `p` is `[1, 2]`. - fn submit_parachain_heads_with_n_parachains(_p: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `388` - // Estimated: `2543` - // Minimum execution time: 31_197_000 picoseconds. - Weight::from_parts(32_362_159, 0) - .saturating_add(Weight::from_parts(0, 2543)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `BridgeKusamaParachains::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::ImportedHeaders` (r:1 w:0) - /// Proof: `BridgeKusamaGrandpa::ImportedHeaders` (`max_values`: Some(1200), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ParasInfo` (r:1 w:1) - /// Proof: `BridgeKusamaParachains::ParasInfo` (`max_values`: Some(1), `max_size`: Some(60), added: 555, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHashes` (r:1 w:1) - /// Proof: `BridgeKusamaParachains::ImportedParaHashes` (`max_values`: Some(600), `max_size`: Some(64), added: 1549, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:0 w:1) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - fn submit_parachain_heads_with_1kb_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `388` - // Estimated: `2543` - // Minimum execution time: 32_948_000 picoseconds. - Weight::from_parts(33_517_000, 0) - .saturating_add(Weight::from_parts(0, 2543)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `BridgeKusamaParachains::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaParachains::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaGrandpa::ImportedHeaders` (r:1 w:0) - /// Proof: `BridgeKusamaGrandpa::ImportedHeaders` (`max_values`: Some(1200), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ParasInfo` (r:1 w:1) - /// Proof: `BridgeKusamaParachains::ParasInfo` (`max_values`: Some(1), `max_size`: Some(60), added: 555, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHashes` (r:1 w:1) - /// Proof: `BridgeKusamaParachains::ImportedParaHashes` (`max_values`: Some(600), `max_size`: Some(64), added: 1549, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaParachains::ImportedParaHeads` (r:0 w:1) - /// Proof: `BridgeKusamaParachains::ImportedParaHeads` (`max_values`: Some(600), `max_size`: Some(196), added: 1681, mode: `MaxEncodedLen`) - fn submit_parachain_heads_with_16kb_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `388` - // Estimated: `2543` - // Minimum execution time: 61_509_000 picoseconds. - Weight::from_parts(62_413_000, 0) - .saturating_add(Weight::from_parts(0, 2543)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(3)) - } -} diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_relayers.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_relayers.rs deleted file mode 100644 index c859feb..0000000 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_bridge_relayers.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md -// for a list of specific contributors. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -//! Autogenerated weights for `pallet_bridge_relayers` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=./bridge-hub-polkadot-chain-spec.json -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_relayers -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ -// --header=./file_header.txt - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_bridge_relayers`. -pub struct WeightInfo(PhantomData); -impl pallet_bridge_relayers::WeightInfo for WeightInfo { - /// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1) - /// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn claim_rewards() -> Weight { - // Proof Size summary in bytes: - // Measured: `278` - // Estimated: `3593` - // Minimum execution time: 43_509_000 picoseconds. - Weight::from_parts(44_237_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1) - /// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) - /// Proof: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) - /// Storage: `Balances::Reserves` (r:1 w:1) - /// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`) - fn register() -> Weight { - // Proof Size summary in bytes: - // Measured: `115` - // Estimated: `4714` - // Minimum execution time: 22_745_000 picoseconds. - Weight::from_parts(22_970_000, 0) - .saturating_add(Weight::from_parts(0, 4714)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1) - /// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) - /// Storage: `Balances::Reserves` (r:1 w:1) - /// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`) - fn deregister() -> Weight { - // Proof Size summary in bytes: - // Measured: `231` - // Estimated: `4714` - // Minimum execution time: 24_959_000 picoseconds. - Weight::from_parts(25_262_000, 0) - .saturating_add(Weight::from_parts(0, 4714)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1) - /// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) - /// Storage: `Balances::Reserves` (r:1 w:1) - /// Proof: `Balances::Reserves` (`max_values`: None, `max_size`: Some(1249), added: 3724, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) - fn slash_and_deregister() -> Weight { - // Proof Size summary in bytes: - // Measured: `334` - // Estimated: `4714` - // Minimum execution time: 27_353_000 picoseconds. - Weight::from_parts(27_970_000, 0) - .saturating_add(Weight::from_parts(0, 4714)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1) - /// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - fn register_relayer_reward() -> Weight { - // Proof Size summary in bytes: - // Measured: `76` - // Estimated: `3538` - // Minimum execution time: 5_110_000 picoseconds. - Weight::from_parts(5_473_000, 0) - .saturating_add(Weight::from_parts(0, 3538)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_collator_selection.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_collator_selection.rs index 04ef287..5e3323e 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_collator_selection.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/pallet_collator_selection.rs @@ -19,20 +19,20 @@ //! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./asset-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=./asset-hub-polkadot-chain-spec.json // --steps=50 // --repeat=20 // --pallet=pallet_collator_selection // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./asset-hub-polkadot-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -55,11 +55,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `196 + b * (79 ±0)` // Estimated: `1187 + b * (2555 ±0)` - // Minimum execution time: 11_117_000 picoseconds. - Weight::from_parts(8_246_810, 0) + // Minimum execution time: 11_068_000 picoseconds. + Weight::from_parts(8_480_360, 0) .saturating_add(Weight::from_parts(0, 1187)) - // Standard Error: 5_915 - .saturating_add(Weight::from_parts(3_144_195, 0).saturating_mul(b.into())) + // Standard Error: 6_186 + .saturating_add(Weight::from_parts(3_123_328, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(b.into()))) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 2555).saturating_mul(b.into())) @@ -78,13 +78,13 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `794 + b * (32 ±0) + c * (53 ±0)` // Estimated: `6287 + b * (37 ±0) + c * (53 ±0)` - // Minimum execution time: 37_811_000 picoseconds. - Weight::from_parts(36_633_430, 0) + // Minimum execution time: 37_988_000 picoseconds. + Weight::from_parts(39_615_334, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 8_479 - .saturating_add(Weight::from_parts(103_826, 0).saturating_mul(b.into())) - // Standard Error: 1_607 - .saturating_add(Weight::from_parts(208_295, 0).saturating_mul(c.into())) + // Standard Error: 10_458 + .saturating_add(Weight::from_parts(47_208, 0).saturating_mul(b.into())) + // Standard Error: 1_982 + .saturating_add(Weight::from_parts(146_581, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) .saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into())) @@ -99,11 +99,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `119 + b * (32 ±0)` // Estimated: `6287` - // Minimum execution time: 10_858_000 picoseconds. - Weight::from_parts(10_475_537, 0) + // Minimum execution time: 11_096_000 picoseconds. + Weight::from_parts(11_018_901, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 3_699 - .saturating_add(Weight::from_parts(186_563, 0).saturating_mul(b.into())) + // Standard Error: 2_382 + .saturating_add(Weight::from_parts(164_625, 0).saturating_mul(b.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -113,8 +113,8 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_944_000 picoseconds. - Weight::from_parts(4_182_000, 0) + // Minimum execution time: 4_057_000 picoseconds. + Weight::from_parts(4_317_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -132,13 +132,13 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `0 + c * (182 ±0) + k * (115 ±0)` // Estimated: `6287 + c * (901 ±29) + k * (901 ±29)` - // Minimum execution time: 9_067_000 picoseconds. - Weight::from_parts(9_253_000, 0) + // Minimum execution time: 9_386_000 picoseconds. + Weight::from_parts(9_467_000, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 154_915 - .saturating_add(Weight::from_parts(5_263_487, 0).saturating_mul(c.into())) - // Standard Error: 154_915 - .saturating_add(Weight::from_parts(4_895_475, 0).saturating_mul(k.into())) + // Standard Error: 152_424 + .saturating_add(Weight::from_parts(5_140_234, 0).saturating_mul(c.into())) + // Standard Error: 152_424 + .saturating_add(Weight::from_parts(4_870_500, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) @@ -155,11 +155,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `319 + c * (49 ±0)` // Estimated: `6287` - // Minimum execution time: 23_358_000 picoseconds. - Weight::from_parts(24_896_978, 0) + // Minimum execution time: 23_799_000 picoseconds. + Weight::from_parts(26_493_236, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 1_437 - .saturating_add(Weight::from_parts(174_963, 0).saturating_mul(c.into())) + // Standard Error: 1_491 + .saturating_add(Weight::from_parts(120_792, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -178,11 +178,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `764 + c * (52 ±0)` // Estimated: `6287 + c * (54 ±0)` - // Minimum execution time: 31_865_000 picoseconds. - Weight::from_parts(34_284_692, 0) + // Minimum execution time: 30_402_000 picoseconds. + Weight::from_parts(35_083_785, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 2_054 - .saturating_add(Weight::from_parts(199_851, 0).saturating_mul(c.into())) + // Standard Error: 2_028 + .saturating_add(Weight::from_parts(129_207, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 54).saturating_mul(c.into())) @@ -204,11 +204,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `904 + c * (53 ±0)` // Estimated: `6287 + c * (54 ±0)` - // Minimum execution time: 45_978_000 picoseconds. - Weight::from_parts(50_228_169, 0) + // Minimum execution time: 49_025_000 picoseconds. + Weight::from_parts(53_124_168, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 3_771 - .saturating_add(Weight::from_parts(256_148, 0).saturating_mul(c.into())) + // Standard Error: 2_369 + .saturating_add(Weight::from_parts(155_477, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(Weight::from_parts(0, 54).saturating_mul(c.into())) @@ -224,11 +224,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `347 + c * (48 ±0)` // Estimated: `6287` - // Minimum execution time: 26_577_000 picoseconds. - Weight::from_parts(28_803_953, 0) + // Minimum execution time: 26_963_000 picoseconds. + Weight::from_parts(30_457_105, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 2_445 - .saturating_add(Weight::from_parts(203_453, 0).saturating_mul(c.into())) + // Standard Error: 2_238 + .saturating_add(Weight::from_parts(132_028, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -242,8 +242,8 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `155` // Estimated: `6196` - // Minimum execution time: 36_982_000 picoseconds. - Weight::from_parts(38_073_000, 0) + // Minimum execution time: 38_303_000 picoseconds. + Weight::from_parts(38_992_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) @@ -266,11 +266,11 @@ impl pallet_collator_selection::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `2302 + c * (97 ±0) + r * (114 ±0)` // Estimated: `6287 + c * (2519 ±0) + r * (2603 ±0)` - // Minimum execution time: 17_745_000 picoseconds. - Weight::from_parts(18_102_000, 0) + // Minimum execution time: 18_298_000 picoseconds. + Weight::from_parts(18_555_000, 0) .saturating_add(Weight::from_parts(0, 6287)) - // Standard Error: 278_847 - .saturating_add(Weight::from_parts(12_401_027, 0).saturating_mul(c.into())) + // Standard Error: 276_687 + .saturating_add(Weight::from_parts(12_078_744, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_multisig.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_multisig.rs index b1c095d..b82e421 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_multisig.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/pallet_multisig.rs @@ -1,4 +1,4 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// Copyright (C) Paseo and the various Paseo contributors, see Contributions.md // for a list of specific contributors. // SPDX-License-Identifier: Apache-2.0 @@ -13,26 +13,27 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! HOSTNAME: `p-ch-hmb-vm-vapas-002`, CPU: `Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("runtimes/chain-specs/asset-hub-local.raw.json")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./polkadot-parachain // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=runtimes/chain-specs/asset-hub-local.raw.json // --steps=50 // --repeat=20 // --pallet=pallet_multisig // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./paseo-asset-hub-local-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -51,11 +52,11 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_689_000 picoseconds. - Weight::from_parts(13_444_130, 0) + // Minimum execution time: 14_849_000 picoseconds. + Weight::from_parts(16_175_879, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 10 - .saturating_add(Weight::from_parts(523, 0).saturating_mul(z.into())) + // Standard Error: 34 + .saturating_add(Weight::from_parts(911, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -65,13 +66,13 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 37_849_000 picoseconds. - Weight::from_parts(27_193_990, 0) + // Minimum execution time: 46_209_000 picoseconds. + Weight::from_parts(36_459_792, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_079 - .saturating_add(Weight::from_parts(124_966, 0).saturating_mul(s.into())) - // Standard Error: 10 - .saturating_add(Weight::from_parts(1_428, 0).saturating_mul(z.into())) + // Standard Error: 2_341 + .saturating_add(Weight::from_parts(132_974, 0).saturating_mul(s.into())) + // Standard Error: 22 + .saturating_add(Weight::from_parts(1_675, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -83,13 +84,13 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 25_182_000 picoseconds. - Weight::from_parts(15_769_176, 0) + // Minimum execution time: 30_920_000 picoseconds. + Weight::from_parts(24_407_953, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 687 - .saturating_add(Weight::from_parts(109_978, 0).saturating_mul(s.into())) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_429, 0).saturating_mul(z.into())) + // Standard Error: 2_978 + .saturating_add(Weight::from_parts(110_964, 0).saturating_mul(s.into())) + // Standard Error: 29 + .saturating_add(Weight::from_parts(1_387, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -103,13 +104,13 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `388 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 43_583_000 picoseconds. - Weight::from_parts(30_311_181, 0) + // Minimum execution time: 53_333_000 picoseconds. + Weight::from_parts(39_509_073, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_428 - .saturating_add(Weight::from_parts(162_543, 0).saturating_mul(s.into())) - // Standard Error: 14 - .saturating_add(Weight::from_parts(1_499, 0).saturating_mul(z.into())) + // Standard Error: 3_225 + .saturating_add(Weight::from_parts(176_813, 0).saturating_mul(s.into())) + // Standard Error: 31 + .saturating_add(Weight::from_parts(1_711, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -120,11 +121,11 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 25_753_000 picoseconds. - Weight::from_parts(26_202_739, 0) + // Minimum execution time: 31_636_000 picoseconds. + Weight::from_parts(33_892_093, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 746 - .saturating_add(Weight::from_parts(117_420, 0).saturating_mul(s.into())) + // Standard Error: 3_147 + .saturating_add(Weight::from_parts(123_769, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -135,11 +136,11 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 14_634_000 picoseconds. - Weight::from_parts(15_097_279, 0) + // Minimum execution time: 18_047_000 picoseconds. + Weight::from_parts(19_420_726, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 882 - .saturating_add(Weight::from_parts(104_968, 0).saturating_mul(s.into())) + // Standard Error: 1_857 + .saturating_add(Weight::from_parts(112_747, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -150,11 +151,11 @@ impl pallet_multisig::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `454 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 27_390_000 picoseconds. - Weight::from_parts(28_089_652, 0) + // Minimum execution time: 33_075_000 picoseconds. + Weight::from_parts(31_323_516, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_148 - .saturating_add(Weight::from_parts(117_661, 0).saturating_mul(s.into())) + // Standard Error: 7_456 + .saturating_add(Weight::from_parts(262_662, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_timestamp.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_timestamp.rs index c006d53..e3d7bf4 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_timestamp.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/pallet_timestamp.rs @@ -1,4 +1,4 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// Copyright (C) Paseo and the various Paseo contributors, see Contributions.md // for a list of specific contributors. // SPDX-License-Identifier: Apache-2.0 @@ -13,26 +13,27 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + //! Autogenerated weights for `pallet_timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! HOSTNAME: `p-ch-hmb-vm-vapas-002`, CPU: `Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("runtimes/chain-specs/asset-hub-local.raw.json")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./polkadot-parachain // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=runtimes/chain-specs/asset-hub-local.raw.json // --steps=50 // --repeat=20 // --pallet=pallet_timestamp // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./paseo-asset-hub-local-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -52,10 +53,10 @@ impl pallet_timestamp::WeightInfo for WeightInfo { /// Proof: `Aura::CurrentSlot` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) fn set() -> Weight { // Proof Size summary in bytes: - // Measured: `49` + // Measured: `86` // Estimated: `1493` - // Minimum execution time: 5_255_000 picoseconds. - Weight::from_parts(5_440_000, 0) + // Minimum execution time: 7_849_000 picoseconds. + Weight::from_parts(8_447_000, 0) .saturating_add(Weight::from_parts(0, 1493)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -64,8 +65,8 @@ impl pallet_timestamp::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `57` // Estimated: `0` - // Minimum execution time: 2_715_000 picoseconds. - Weight::from_parts(2_799_000, 0) + // Minimum execution time: 3_321_000 picoseconds. + Weight::from_parts(3_460_000, 0) .saturating_add(Weight::from_parts(0, 0)) } } diff --git a/system-parachains/bridge-hub-paseo/src/weights/pallet_xcm.rs b/system-parachains/bridge-hub-paseo/src/weights/pallet_xcm.rs index 04384b7..8d8f588 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/pallet_xcm.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/pallet_xcm.rs @@ -19,20 +19,20 @@ //! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./asset-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 // Executed Command: // ./target/production/polkadot // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=./asset-hub-polkadot-chain-spec.json // --steps=50 // --repeat=20 // --pallet=pallet_xcm // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/ +// --output=./asset-hub-polkadot-weights/ // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -62,8 +62,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3540` - // Minimum execution time: 19_634_000 picoseconds. - Weight::from_parts(20_057_000, 0) + // Minimum execution time: 20_417_000 picoseconds. + Weight::from_parts(21_346_000, 0) .saturating_add(Weight::from_parts(0, 3540)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) @@ -78,7 +78,7 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -86,26 +86,50 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn teleport_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `107` + // Measured: `75` // Estimated: `3593` - // Minimum execution time: 77_202_000 picoseconds. - Weight::from_parts(79_538_000, 0) + // Minimum execution time: 90_570_000 picoseconds. + Weight::from_parts(93_009_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes(3)) } - /// Storage: `Benchmark::Override` (r:0 w:0) - /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) fn reserve_transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) - .saturating_add(Weight::from_parts(0, 0)) + // Measured: `296` + // Estimated: `6196` + // Minimum execution time: 117_416_000 picoseconds. + Weight::from_parts(119_561_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Assets::Asset` (r:1 w:1) + /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`) + /// Storage: `Assets::Account` (r:2 w:2) + /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) @@ -114,21 +138,19 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `3593` - // Minimum execution time: 77_293_000 picoseconds. - Weight::from_parts(78_958_000, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `478` + // Estimated: `6208` + // Minimum execution time: 142_386_000 picoseconds. + Weight::from_parts(146_203_000, 0) + .saturating_add(Weight::from_parts(0, 6208)) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(7)) } /// Storage: `Benchmark::Override` (r:0 w:0) /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -146,8 +168,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_894_000 picoseconds. - Weight::from_parts(6_160_000, 0) + // Minimum execution time: 5_982_000 picoseconds. + Weight::from_parts(6_301_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -157,8 +179,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_946_000 picoseconds. - Weight::from_parts(2_031_000, 0) + // Minimum execution time: 2_050_000 picoseconds. + Weight::from_parts(2_183_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -184,8 +206,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3540` - // Minimum execution time: 25_360_000 picoseconds. - Weight::from_parts(25_956_000, 0) + // Minimum execution time: 26_197_000 picoseconds. + Weight::from_parts(26_616_000, 0) .saturating_add(Weight::from_parts(0, 3540)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -208,11 +230,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_unsubscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `293` - // Estimated: `3758` - // Minimum execution time: 28_338_000 picoseconds. - Weight::from_parts(28_958_000, 0) - .saturating_add(Weight::from_parts(0, 3758)) + // Measured: `292` + // Estimated: `3757` + // Minimum execution time: 27_668_000 picoseconds. + Weight::from_parts(28_414_000, 0) + .saturating_add(Weight::from_parts(0, 3757)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -222,8 +244,8 @@ impl pallet_xcm::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_898_000 picoseconds. - Weight::from_parts(2_035_000, 0) + // Minimum execution time: 2_038_000 picoseconds. + Weight::from_parts(2_228_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -231,11 +253,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `89` - // Estimated: `13454` - // Minimum execution time: 16_115_000 picoseconds. - Weight::from_parts(16_440_000, 0) - .saturating_add(Weight::from_parts(0, 13454)) + // Measured: `125` + // Estimated: `13490` + // Minimum execution time: 18_130_000 picoseconds. + Weight::from_parts(18_553_000, 0) + .saturating_add(Weight::from_parts(0, 13490)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -243,11 +265,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `93` - // Estimated: `13458` - // Minimum execution time: 16_214_000 picoseconds. - Weight::from_parts(16_600_000, 0) - .saturating_add(Weight::from_parts(0, 13458)) + // Measured: `129` + // Estimated: `13494` + // Minimum execution time: 18_447_000 picoseconds. + Weight::from_parts(18_864_000, 0) + .saturating_add(Weight::from_parts(0, 13494)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -255,11 +277,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: - // Measured: `106` - // Estimated: `15946` - // Minimum execution time: 18_542_000 picoseconds. - Weight::from_parts(19_436_000, 0) - .saturating_add(Weight::from_parts(0, 15946)) + // Measured: `140` + // Estimated: `15980` + // Minimum execution time: 20_401_000 picoseconds. + Weight::from_parts(20_657_000, 0) + .saturating_add(Weight::from_parts(0, 15980)) .saturating_add(T::DbWeight::get().reads(6)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) @@ -278,11 +300,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn notify_current_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `143` - // Estimated: `6083` - // Minimum execution time: 25_126_000 picoseconds. - Weight::from_parts(25_924_000, 0) - .saturating_add(Weight::from_parts(0, 6083)) + // Measured: `142` + // Estimated: `6082` + // Minimum execution time: 25_133_000 picoseconds. + Weight::from_parts(25_527_000, 0) + .saturating_add(Weight::from_parts(0, 6082)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(3)) } @@ -290,22 +312,22 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `136` - // Estimated: `11026` - // Minimum execution time: 10_789_000 picoseconds. - Weight::from_parts(11_131_000, 0) - .saturating_add(Weight::from_parts(0, 11026)) + // Measured: `172` + // Estimated: `11062` + // Minimum execution time: 11_596_000 picoseconds. + Weight::from_parts(11_894_000, 0) + .saturating_add(Weight::from_parts(0, 11062)) .saturating_add(T::DbWeight::get().reads(4)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notify_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `100` - // Estimated: `13465` - // Minimum execution time: 16_310_000 picoseconds. - Weight::from_parts(16_904_000, 0) - .saturating_add(Weight::from_parts(0, 13465)) + // Measured: `136` + // Estimated: `13501` + // Minimum execution time: 18_513_000 picoseconds. + Weight::from_parts(19_028_000, 0) + .saturating_add(Weight::from_parts(0, 13501)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -325,11 +347,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `143` - // Estimated: `13508` - // Minimum execution time: 33_444_000 picoseconds. - Weight::from_parts(34_343_000, 0) - .saturating_add(Weight::from_parts(0, 13508)) + // Measured: `142` + // Estimated: `13507` + // Minimum execution time: 33_572_000 picoseconds. + Weight::from_parts(34_292_000, 0) + .saturating_add(Weight::from_parts(0, 13507)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -339,11 +361,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn new_query() -> Weight { // Proof Size summary in bytes: - // Measured: `32` - // Estimated: `1517` - // Minimum execution time: 3_397_000 picoseconds. - Weight::from_parts(3_528_000, 0) - .saturating_add(Weight::from_parts(0, 1517)) + // Measured: `69` + // Estimated: `1554` + // Minimum execution time: 4_725_000 picoseconds. + Weight::from_parts(5_006_000, 0) + .saturating_add(Weight::from_parts(0, 1554)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -351,11 +373,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn take_response() -> Weight { // Proof Size summary in bytes: - // Measured: `7669` - // Estimated: `11134` - // Minimum execution time: 23_354_000 picoseconds. - Weight::from_parts(23_823_000, 0) - .saturating_add(Weight::from_parts(0, 11134)) + // Measured: `7706` + // Estimated: `11171` + // Minimum execution time: 25_548_000 picoseconds. + Weight::from_parts(26_063_000, 0) + .saturating_add(Weight::from_parts(0, 11171)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -363,11 +385,11 @@ impl pallet_xcm::WeightInfo for WeightInfo { /// Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) fn claim_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `90` - // Estimated: `3555` - // Minimum execution time: 33_922_000 picoseconds. - Weight::from_parts(34_433_000, 0) - .saturating_add(Weight::from_parts(0, 3555)) + // Measured: `126` + // Estimated: `3591` + // Minimum execution time: 36_411_000 picoseconds. + Weight::from_parts(37_294_000, 0) + .saturating_add(Weight::from_parts(0, 3591)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_ethereum_client.rs b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_ethereum_client.rs index 5e00a85..991971e 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_ethereum_client.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_ethereum_client.rs @@ -69,7 +69,7 @@ impl snowbridge_pallet_ethereum_client::WeightInfo for // Measured: `114` // Estimated: `3501` // Minimum execution time: 101_311_912_000 picoseconds. - Weight::from_parts(101_492_831_000, 0) + Weight::from_parts(131_940_680_300, 0) .saturating_add(Weight::from_parts(0, 3501)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(9)) @@ -93,7 +93,7 @@ impl snowbridge_pallet_ethereum_client::WeightInfo for // Measured: `92787` // Estimated: `93857` // Minimum execution time: 25_164_795_000 picoseconds. - Weight::from_parts(25_229_383_000, 0) + Weight::from_parts(32_798_197_900, 0) .saturating_add(Weight::from_parts(0, 93857)) .saturating_add(T::DbWeight::get().reads(7)) } @@ -116,7 +116,7 @@ impl snowbridge_pallet_ethereum_client::WeightInfo for // Measured: `92787` // Estimated: `93857` // Minimum execution time: 126_786_733_000 picoseconds. - Weight::from_parts(126_936_460_000, 0) + Weight::from_parts(165_017_398_000, 0) .saturating_add(Weight::from_parts(0, 93857)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(1)) @@ -140,7 +140,7 @@ impl snowbridge_pallet_ethereum_client::WeightInfo for // Measured: `418` // Estimated: `3537` // Minimum execution time: 88_695_000 picoseconds. - Weight::from_parts(92_638_000, 0) + Weight::from_parts(120_429_400, 0) .saturating_add(Weight::from_parts(0, 3537)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) diff --git a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_inbound_queue.rs b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_inbound_queue.rs index f912397..196aec1 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_inbound_queue.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_inbound_queue.rs @@ -65,7 +65,7 @@ impl snowbridge_pallet_inbound_queue::WeightInfo for We // Measured: `815` // Estimated: `4280` // Minimum execution time: 104_849_000 picoseconds. - Weight::from_parts(107_855_000, 0) + Weight::from_parts(140_211_500, 0) .saturating_add(Weight::from_parts(0, 4280)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(2)) diff --git a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_outbound_queue.rs b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_outbound_queue.rs index 0f554e6..681feda 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_outbound_queue.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_outbound_queue.rs @@ -59,7 +59,7 @@ impl snowbridge_pallet_outbound_queue::WeightInfo for W // Measured: `81` // Estimated: `3513` // Minimum execution time: 28_111_000 picoseconds. - Weight::from_parts(28_570_000, 0) + Weight::from_parts(37_141_000, 0) .saturating_add(Weight::from_parts(0, 3513)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -73,7 +73,7 @@ impl snowbridge_pallet_outbound_queue::WeightInfo for W // Measured: `1057` // Estimated: `2542` // Minimum execution time: 27_193_000 picoseconds. - Weight::from_parts(27_384_000, 0) + Weight::from_parts(35_599_200, 0) .saturating_add(Weight::from_parts(0, 2542)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -87,7 +87,7 @@ impl snowbridge_pallet_outbound_queue::WeightInfo for W // Measured: `64` // Estimated: `1549` // Minimum execution time: 7_062_000 picoseconds. - Weight::from_parts(7_331_000, 0) + Weight::from_parts(9_530_300, 0) .saturating_add(Weight::from_parts(0, 1549)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) diff --git a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_system.rs b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_system.rs index 4db436f..086d054 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_system.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/snowbridge_pallet_system.rs @@ -61,7 +61,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `219` // Estimated: `3601` // Minimum execution time: 32_064_000 picoseconds. - Weight::from_parts(32_545_000, 0) + Weight::from_parts(42_308_500, 0) .saturating_add(Weight::from_parts(0, 3601)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -81,7 +81,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `219` // Estimated: `3601` // Minimum execution time: 24_339_000 picoseconds. - Weight::from_parts(25_149_000, 0) + Weight::from_parts(32_693_700, 0) .saturating_add(Weight::from_parts(0, 3601)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -101,7 +101,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `219` // Estimated: `3601` // Minimum execution time: 29_237_000 picoseconds. - Weight::from_parts(29_824_000, 0) + Weight::from_parts(38_771_200, 0) .saturating_add(Weight::from_parts(0, 3601)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) @@ -127,7 +127,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `485` // Estimated: `6196` // Minimum execution time: 61_956_000 picoseconds. - Weight::from_parts(63_946_000, 0) + Weight::from_parts(83_129_800, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(6)) @@ -151,7 +151,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `930` // Estimated: `69078` // Minimum execution time: 73_087_000 picoseconds. - Weight::from_parts(75_308_000, 0) + Weight::from_parts(97_900_400, 0) .saturating_add(Weight::from_parts(0, 69078)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) @@ -175,7 +175,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `716` // Estimated: `6212` // Minimum execution time: 70_147_000 picoseconds. - Weight::from_parts(71_396_000, 0) + Weight::from_parts(92_814_800, 0) .saturating_add(Weight::from_parts(0, 6212)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(5)) @@ -195,7 +195,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `548` // Estimated: `6212` // Minimum execution time: 36_346_000 picoseconds. - Weight::from_parts(37_302_000, 0) + Weight::from_parts(48_492_600, 0) .saturating_add(Weight::from_parts(0, 6212)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -221,7 +221,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `815` // Estimated: `6212` // Minimum execution time: 73_833_000 picoseconds. - Weight::from_parts(75_407_000, 0) + Weight::from_parts(98_029_100, 0) .saturating_add(Weight::from_parts(0, 6212)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(5)) @@ -243,7 +243,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `570` // Estimated: `6212` // Minimum execution time: 40_908_000 picoseconds. - Weight::from_parts(41_888_000, 0) + Weight::from_parts(54_454_400, 0) .saturating_add(Weight::from_parts(0, 6212)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(3)) @@ -263,7 +263,7 @@ impl snowbridge_pallet_system::WeightInfo for WeightInf // Measured: `219` // Estimated: `3601` // Minimum execution time: 26_585_000 picoseconds. - Weight::from_parts(27_216_000, 0) + Weight::from_parts(35_380_800, 0) .saturating_add(Weight::from_parts(0, 3601)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) diff --git a/system-parachains/bridge-hub-paseo/src/weights/xcm/mod.rs b/system-parachains/bridge-hub-paseo/src/weights/xcm/mod.rs index 8f60b01..0e6fbc3 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/xcm/mod.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/xcm/mod.rs @@ -18,7 +18,6 @@ mod pallet_xcm_benchmarks_fungible; mod pallet_xcm_benchmarks_generic; use crate::{xcm_config::MaxAssetsIntoHolding, Runtime}; -use codec::Encode; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; use sp_std::prelude::*; @@ -197,11 +196,10 @@ impl XcmWeightInfo for BridgeHubPolkadotXcmWeight { XcmGeneric::::clear_transact_status() } fn universal_origin(_: &Junction) -> Weight { - Weight::MAX + XcmGeneric::::universal_origin() } - fn export_message(_: &NetworkId, _: &Junctions, inner: &Xcm<()>) -> Weight { - let inner_encoded_len = inner.encode().len() as u32; - XcmGeneric::::export_message(inner_encoded_len) + fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { + Weight::MAX } fn lock_asset(_: &Asset, _: &Location) -> Weight { Weight::MAX diff --git a/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs b/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs index 8d22a64..2d23dec 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs @@ -1,4 +1,4 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// Copyright (C) Paseo and the various Paseo contributors, see Contributions.md // for a list of specific contributors. // SPDX-License-Identifier: Apache-2.0 @@ -13,26 +13,27 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + //! Autogenerated weights for `pallet_xcm_benchmarks::fungible` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! HOSTNAME: `p-ch-hmb-vm-vapas-002`, CPU: `Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("runtimes/chain-specs/asset-hub-local.raw.json")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./polkadot-parachain // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=runtimes/chain-specs/asset-hub-local.raw.json // --steps=50 // --repeat=20 // --pallet=pallet_xcm_benchmarks::fungible // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/xcm/pallet_xcm_benchmarks_fungible.rs +// --output=./paseo-asset-hub-local-weights/xcm/pallet_xcm_benchmarks_fungible.rs // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -52,8 +53,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `101` // Estimated: `3593` - // Minimum execution time: 27_749_000 picoseconds. - Weight::from_parts(28_473_000, 0) + // Minimum execution time: 70_410_000 picoseconds. + Weight::from_parts(84_407_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -64,13 +65,13 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `153` // Estimated: `6196` - // Minimum execution time: 37_673_000 picoseconds. - Weight::from_parts(38_330_000, 0) + // Minimum execution time: 56_301_000 picoseconds. + Weight::from_parts(80_450_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: `System::Account` (r:3 w:2) + /// Storage: `System::Account` (r:3 w:3) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -88,13 +89,13 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn transfer_reserve_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `260` + // Measured: `228` // Estimated: `8799` - // Minimum execution time: 78_356_000 picoseconds. - Weight::from_parts(80_180_000, 0) + // Minimum execution time: 107_784_000 picoseconds. + Weight::from_parts(126_285_000, 0) .saturating_add(Weight::from_parts(0, 8799)) .saturating_add(T::DbWeight::get().reads(10)) - .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes(5)) } /// Storage: `Benchmark::Override` (r:0 w:0) /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -102,8 +103,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. - Weight::from_parts(18_446_744_073_709_551_000, 0) + // Minimum execution time: 4_860_700 picoseconds. + Weight::from_parts(4_860_700, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) @@ -116,7 +117,7 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -124,20 +125,20 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn initiate_reserve_withdraw() -> Weight { // Proof Size summary in bytes: - // Measured: `208` + // Measured: `176` // Estimated: `6196` - // Minimum execution time: 48_088_000 picoseconds. - Weight::from_parts(49_343_000, 0) + // Minimum execution time: 247_911_000 picoseconds. + Weight::from_parts(266_827_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } pub(crate) fn receive_teleported_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_705_000 picoseconds. - Weight::from_parts(2_797_000, 0) + // Minimum execution time: 4_594_000 picoseconds. + Weight::from_parts(5_091_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `System::Account` (r:1 w:1) @@ -146,14 +147,12 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `52` // Estimated: `3593` - // Minimum execution time: 21_715_000 picoseconds. - Weight::from_parts(22_032_000, 0) + // Minimum execution time: 38_329_000 picoseconds. + Weight::from_parts(42_150_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) @@ -162,21 +161,23 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn deposit_reserve_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `159` + // Measured: `127` // Estimated: `6196` - // Minimum execution time: 55_124_000 picoseconds. - Weight::from_parts(56_361_000, 0) + // Minimum execution time: 178_335_000 picoseconds. + Weight::from_parts(185_290_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -188,7 +189,7 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:1 w:0) + /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -196,12 +197,12 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn initiate_teleport() -> Weight { // Proof Size summary in bytes: - // Measured: `107` + // Measured: `75` // Estimated: `3593` - // Minimum execution time: 25_317_000 picoseconds. - Weight::from_parts(26_148_000, 0) + // Minimum execution time: 66_314_000 picoseconds. + Weight::from_parts(68_619_000, 0) .saturating_add(Weight::from_parts(0, 3593)) .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index e051439..f4ac8cf 100644 --- a/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/system-parachains/bridge-hub-paseo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -1,4 +1,4 @@ -// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// Copyright (C) Paseo and the various Paseo contributors, see Contributions.md // for a list of specific contributors. // SPDX-License-Identifier: Apache-2.0 @@ -13,26 +13,27 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + //! Autogenerated weights for `pallet_xcm_benchmarks::generic` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-03-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ggwpez-ref-hw`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("./bridge-hub-polkadot-chain-spec.json")`, DB CACHE: 1024 +//! HOSTNAME: `p-ch-hmb-vm-vapas-002`, CPU: `Intel(R) Xeon(R) Silver 4314 CPU @ 2.40GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("runtimes/chain-specs/asset-hub-local.raw.json")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// ./polkadot-parachain // benchmark // pallet -// --chain=./bridge-hub-polkadot-chain-spec.json +// --chain=runtimes/chain-specs/asset-hub-local.raw.json // --steps=50 // --repeat=20 // --pallet=pallet_xcm_benchmarks::generic // --extrinsic=* // --wasm-execution=compiled // --heap-pages=4096 -// --output=./bridge-hub-polkadot-weights/xcm/pallet_xcm_benchmarks_generic.rs +// --output=./paseo-asset-hub-local-weights/xcm/pallet_xcm_benchmarks_generic.rs // --header=./file_header.txt #![cfg_attr(rustfmt, rustfmt_skip)] @@ -56,7 +57,7 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -64,87 +65,87 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn report_holding() -> Weight { // Proof Size summary in bytes: - // Measured: `208` + // Measured: `176` // Estimated: `6196` - // Minimum execution time: 46_970_000 picoseconds. - Weight::from_parts(48_603_000, 0) + // Minimum execution time: 521_910_000 picoseconds. + Weight::from_parts(531_741_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } pub(crate) fn buy_execution() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_247_000 picoseconds. - Weight::from_parts(1_351_000, 0) + // Minimum execution time: 3_805_000 picoseconds. + Weight::from_parts(3_902_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `PolkadotXcm::Queries` (r:1 w:0) /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) pub(crate) fn query_response() -> Weight { // Proof Size summary in bytes: - // Measured: `32` - // Estimated: `3497` - // Minimum execution time: 6_555_000 picoseconds. - Weight::from_parts(6_703_000, 0) - .saturating_add(Weight::from_parts(0, 3497)) + // Measured: `69` + // Estimated: `3534` + // Minimum execution time: 11_221_000 picoseconds. + Weight::from_parts(11_702_000, 0) + .saturating_add(Weight::from_parts(0, 3534)) .saturating_add(T::DbWeight::get().reads(1)) } pub(crate) fn transact() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_333_000 picoseconds. - Weight::from_parts(6_728_000, 0) + // Minimum execution time: 11_815_000 picoseconds. + Weight::from_parts(12_254_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn refund_surplus() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_943_000 picoseconds. - Weight::from_parts(2_051_000, 0) + // Minimum execution time: 43_714_000 picoseconds. + Weight::from_parts(43_892_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn set_error_handler() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_264_000 picoseconds. - Weight::from_parts(1_332_000, 0) + // Minimum execution time: 2_381_000 picoseconds. + Weight::from_parts(2_560_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn set_appendix() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_240_000 picoseconds. - Weight::from_parts(1_303_000, 0) + // Minimum execution time: 2_472_000 picoseconds. + Weight::from_parts(2_614_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn clear_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_220_000 picoseconds. - Weight::from_parts(1_292_000, 0) + // Minimum execution time: 2_412_000 picoseconds. + Weight::from_parts(2_505_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn descend_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_293_000 picoseconds. - Weight::from_parts(1_394_000, 0) + // Minimum execution time: 3_426_000 picoseconds. + Weight::from_parts(3_513_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn clear_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_201_000 picoseconds. - Weight::from_parts(1_290_000, 0) + // Minimum execution time: 2_458_000 picoseconds. + Weight::from_parts(2_538_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) @@ -157,7 +158,7 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -165,23 +166,23 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn report_error() -> Weight { // Proof Size summary in bytes: - // Measured: `208` + // Measured: `176` // Estimated: `6196` - // Minimum execution time: 44_226_000 picoseconds. - Weight::from_parts(46_560_000, 0) + // Minimum execution time: 63_825_000 picoseconds. + Weight::from_parts(65_268_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) /// Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) pub(crate) fn claim_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `90` - // Estimated: `3555` - // Minimum execution time: 9_384_000 picoseconds. - Weight::from_parts(9_849_000, 0) - .saturating_add(Weight::from_parts(0, 3555)) + // Measured: `126` + // Estimated: `3591` + // Minimum execution time: 15_456_000 picoseconds. + Weight::from_parts(15_746_000, 0) + .saturating_add(Weight::from_parts(0, 3591)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -189,8 +190,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_267_000 picoseconds. - Weight::from_parts(1_342_000, 0) + // Minimum execution time: 2_417_000 picoseconds. + Weight::from_parts(2_574_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:1 w:1) @@ -211,8 +212,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3540` - // Minimum execution time: 20_511_000 picoseconds. - Weight::from_parts(21_396_000, 0) + // Minimum execution time: 28_414_000 picoseconds. + Weight::from_parts(28_814_000, 0) .saturating_add(Weight::from_parts(0, 3540)) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) @@ -223,8 +224,8 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_127_000 picoseconds. - Weight::from_parts(3_672_000, 0) + // Minimum execution time: 4_526_000 picoseconds. + Weight::from_parts(4_678_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -232,40 +233,40 @@ impl WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_591_000 picoseconds. - Weight::from_parts(1_749_000, 0) + // Minimum execution time: 156_429_000 picoseconds. + Weight::from_parts(156_830_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn expect_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_382_000 picoseconds. - Weight::from_parts(1_447_000, 0) + // Minimum execution time: 14_360_000 picoseconds. + Weight::from_parts(14_653_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn expect_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_245_000 picoseconds. - Weight::from_parts(1_442_000, 0) + // Minimum execution time: 2_552_000 picoseconds. + Weight::from_parts(2_656_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn expect_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_244_000 picoseconds. - Weight::from_parts(1_421_000, 0) + // Minimum execution time: 2_463_000 picoseconds. + Weight::from_parts(2_566_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn expect_transact_status() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_417_000 picoseconds. - Weight::from_parts(1_581_000, 0) + // Minimum execution time: 2_702_000 picoseconds. + Weight::from_parts(2_858_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) @@ -278,7 +279,7 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -286,20 +287,20 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn query_pallet() -> Weight { // Proof Size summary in bytes: - // Measured: `208` + // Measured: `176` // Estimated: `6196` - // Minimum execution time: 48_410_000 picoseconds. - Weight::from_parts(49_318_000, 0) + // Minimum execution time: 69_384_000 picoseconds. + Weight::from_parts(70_717_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } pub(crate) fn expect_pallet() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_099_000 picoseconds. - Weight::from_parts(4_205_000, 0) + // Minimum execution time: 5_710_000 picoseconds. + Weight::from_parts(5_938_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) @@ -312,7 +313,7 @@ impl WeightInfo { /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `System::Account` (r:2 w:1) + /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -320,77 +321,62 @@ impl WeightInfo { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub(crate) fn report_transact_status() -> Weight { // Proof Size summary in bytes: - // Measured: `208` + // Measured: `176` // Estimated: `6196` - // Minimum execution time: 44_221_000 picoseconds. - Weight::from_parts(45_703_000, 0) + // Minimum execution time: 64_437_000 picoseconds. + Weight::from_parts(65_794_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes(4)) } pub(crate) fn clear_transact_status() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_227_000 picoseconds. - Weight::from_parts(1_292_000, 0) + // Minimum execution time: 2_463_000 picoseconds. + Weight::from_parts(2_612_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn set_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_193_000 picoseconds. - Weight::from_parts(1_268_000, 0) + // Minimum execution time: 2_444_000 picoseconds. + Weight::from_parts(2_607_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn clear_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_195_000 picoseconds. - Weight::from_parts(1_279_000, 0) + // Minimum execution time: 2_487_000 picoseconds. + Weight::from_parts(2_576_000, 0) .saturating_add(Weight::from_parts(0, 0)) } - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `PolkadotXcm::SupportedVersion` (r:2 w:0) - /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `BridgeKusamaMessages::PalletOperatingMode` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::OutboundLanes` (r:1 w:1) - /// Proof: `BridgeKusamaMessages::OutboundLanes` (`max_values`: Some(1), `max_size`: Some(44), added: 539, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::OutboundLanesCongestedSignals` (r:1 w:0) - /// Proof: `BridgeKusamaMessages::OutboundLanesCongestedSignals` (`max_values`: Some(1), `max_size`: Some(21), added: 516, mode: `MaxEncodedLen`) - /// Storage: `BridgeKusamaMessages::OutboundMessages` (r:0 w:1) - /// Proof: `BridgeKusamaMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(2621472), added: 2623947, mode: `MaxEncodedLen`) - /// The range of component `x` is `[1, 1000]`. - pub(crate) fn export_message(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `227` - // Estimated: `6167` - // Minimum execution time: 37_717_000 picoseconds. - Weight::from_parts(38_427_457, 0) - .saturating_add(Weight::from_parts(0, 6167)) - // Standard Error: 128 - .saturating_add(Weight::from_parts(43_117, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) - } pub(crate) fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_153_000 picoseconds. - Weight::from_parts(1_246_000, 0) + // Minimum execution time: 2_418_000 picoseconds. + Weight::from_parts(2_555_000, 0) .saturating_add(Weight::from_parts(0, 0)) } pub(crate) fn unpaid_execution() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_182_000 picoseconds. - Weight::from_parts(1_280_000, 0) + // Minimum execution time: 2_577_000 picoseconds. + Weight::from_parts(2_715_000, 0) .saturating_add(Weight::from_parts(0, 0)) } + + pub(crate) fn universal_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1489` + // Minimum execution time: 3_294_000 picoseconds. + Weight::from_parts(3_415_000, 0) + .saturating_add(Weight::from_parts(0, 1489)) + .saturating_add(T::DbWeight::get().reads(1)) + } } diff --git a/system-parachains/bridge-hub-paseo/src/xcm_config.rs b/system-parachains/bridge-hub-paseo/src/xcm_config.rs index 66c6cb7..aedcc72 100644 --- a/system-parachains/bridge-hub-paseo/src/xcm_config.rs +++ b/system-parachains/bridge-hub-paseo/src/xcm_config.rs @@ -15,42 +15,42 @@ // along with Cumulus. If not, see . use super::{ - bridge_to_ethereum_config::EthereumNetwork, - bridge_to_kusama_config::ToBridgeHubKusamaHaulBlobExporter, AccountId, AllPalletsWithSystem, - Balances, CollatorSelection, ParachainInfo, ParachainSystem, PolkadotXcm, - PriceForParentDelivery, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, - XcmpQueue, + bridge_to_ethereum_config::EthereumNetwork, + AccountId, AllPalletsWithSystem, + Balances, CollatorSelection, ParachainInfo, ParachainSystem, PolkadotXcm, + PriceForParentDelivery, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, + XcmpQueue, }; use frame_support::{ - parameter_types, - traits::{tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, Nothing}, + parameter_types, + traits::{tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, Nothing}, }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; use parachains_common::xcm_config::{ - AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, - RelayOrOtherSystemParachains, + AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains, + RelayOrOtherSystemParachains, }; use polkadot_parachain_primitives::primitives::Sibling; -use polkadot_runtime_constants::system_parachain; +use paseo_runtime_constants::system_parachain; use snowbridge_runtime_common::XcmExportFeeToSibling; use sp_runtime::traits::AccountIdConversion; use sp_std::marker::PhantomData; use system_parachains_constants::TREASURY_PALLET_ID; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, - AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, - DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, - FungibleAdapter, HandleFee, HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, - XcmFeeToAccount, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, + AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, DenyReserveTransferToRelayChain, + DenyThenTry, DescribeAllTerminal, DescribeFamily, EnsureXcmOrigin, FrameTransactionalProcessor, + FungibleAdapter, HandleFee, HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + XcmFeeToAccount, }; use xcm_executor::{ - traits::{ConvertLocation, FeeManager, FeeReason, FeeReason::Export}, - XcmExecutor, + traits::{ConvertLocation, FeeManager, FeeReason, FeeReason::Export}, + XcmExecutor, }; parameter_types! { @@ -63,7 +63,7 @@ parameter_types! { pub const MaxAssetsIntoHolding: u32 = 64; pub FellowshipLocation: Location = Location::new(1, Parachain(system_parachain::COLLECTIVES_ID)); pub const GovernanceLocation: Location = Location::parent(); - pub RelayTreasuryLocation: Location = (Parent, PalletInstance(polkadot_runtime_constants::TREASURY_PALLET_ID)).into(); + pub RelayTreasuryLocation: Location = (Parent, PalletInstance(paseo_runtime_constants::TREASURY_PALLET_ID)).into(); pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating(); // Test [`crate::tests::treasury_pallet_account_not_none`] ensures that the result of location // conversion is not `None`. @@ -77,65 +77,65 @@ parameter_types! { /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the parent `AccountId`. - ParentIsPreset, - // Sibling parachain origins convert to AccountId via the `ParaId::into`. - SiblingParachainConvertsVia, - // Straight up local `AccountId32` origins just alias directly to `AccountId`. - AccountId32Aliases, - // Foreign locations alias into accounts according to a hash of their standard description. - HashedDescription>, + // The parent (Relay-chain) origin converts to the parent `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, + // Foreign locations alias into accounts according to a hash of their standard description. + HashedDescription>, ); /// Means for transacting the native currency on this chain. pub type FungibleTransactor = FungibleAdapter< - // Use this currency: - Balances, - // Use this currency when it is a fungible asset matching the given location or name: - IsConcrete, - // Do a simple punn to convert an AccountId32 Location into a native chain account ID: - LocationToAccountId, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We don't track any teleports of `Balances`. - (), + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Do a simple punn to convert an AccountId32 Location into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports of `Balances`. + (), >; /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can /// biases the kind of local `Origin` it will become. pub type XcmOriginToTransactDispatchOrigin = ( - // Sovereign account converter; this attempts to derive an `AccountId` from the origin location - // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for - // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when - // recognized. - RelayChainAsNative, - // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when - // recognized. - SiblingParachainAsNative, - // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a - // transaction from the Root origin. - ParentAsSuperuser, - // Native signed account converter; this just converts an `AccountId32` origin into a normal - // `RuntimeOrigin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, - // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognized. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognized. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `RuntimeOrigin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, ); pub struct ParentOrParentsPlurality; impl Contains for ParentOrParentsPlurality { - fn contains(location: &Location) -> bool { - matches!(location.unpack(), (1, []) | (1, [Plurality { .. }])) - } + fn contains(location: &Location) -> bool { + matches!(location.unpack(), (1, []) | (1, [Plurality { .. }])) + } } pub struct FellowsPlurality; impl Contains for FellowsPlurality { - fn contains(location: &Location) -> bool { - matches!( + fn contains(location: &Location) -> bool { + matches!( location.unpack(), ( 1, @@ -145,46 +145,46 @@ impl Contains for FellowsPlurality { ] ) ) - } + } } pub type Barrier = TrailingSetTopicAsId< - DenyThenTry< - DenyReserveTransferToRelayChain, - ( - // Allow local users to buy weight credit. - TakeWeightCredit, - // Expected responses are OK. - AllowKnownQueryResponses, - WithComputedOrigin< - ( - // If the message is one that immediately attempts to pay for execution, then - // allow it. - AllowTopLevelPaidExecutionFrom, - // Parent, its pluralities (i.e. governance bodies), Fellows plurality - // and relay treasury get free execution. - AllowExplicitUnpaidExecutionFrom<( - ParentOrParentsPlurality, - FellowsPlurality, - Equals, - )>, - // Subscriptions for version tracking are OK. - AllowSubscriptionsFrom, - ), - UniversalLocation, - ConstU32<8>, - >, - ), - >, + DenyThenTry< + DenyReserveTransferToRelayChain, + ( + // Allow local users to buy weight credit. + TakeWeightCredit, + // Expected responses are OK. + AllowKnownQueryResponses, + WithComputedOrigin< + ( + // If the message is one that immediately attempts to pay for execution, then + // allow it. + AllowTopLevelPaidExecutionFrom, + // Parent, its pluralities (i.e. governance bodies), Fellows plurality + // and relay treasury get free execution. + AllowExplicitUnpaidExecutionFrom<( + ParentOrParentsPlurality, + FellowsPlurality, + Equals, + )>, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, + ), + >, >; /// Locations that will not be charged fees in the executor, /// either execution or delivery. /// We only waive fees for system functions, which these locations represent. pub type WaivedLocations = ( - RelayOrOtherSystemParachains, - Equals, - FellowsPlurality, + RelayOrOtherSystemParachains, + Equals, + FellowsPlurality, ); /// Cases where a remote origin is accepted as trusted Teleporter for a given asset: @@ -193,57 +193,56 @@ pub type TrustedTeleporters = ConcreteAssetFromSystem; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; - type AssetTransactor = FungibleTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - // BridgeHub does not recognize a reserve location for any asset. Users must teleport DOT - // where allowed (e.g. with the Relay Chain). - type IsReserve = (); - type IsTeleporter = TrustedTeleporters; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = WeightInfoBounds< - crate::weights::xcm::BridgeHubPolkadotXcmWeight, - RuntimeCall, - MaxInstructions, - >; - type Trader = UsingComponents< - WeightToFee, - DotRelayLocation, - AccountId, - Balances, - ResolveTo, - >; - type ResponseHandler = PolkadotXcm; - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); - type FeeManager = XcmFeeManagerFromComponentsBridgeHub< - WaivedLocations, - ( - XcmExportFeeToSibling< - bp_polkadot::Balance, - AccountId, - DotRelayLocation, - EthereumNetwork, - Self::AssetTransactor, - crate::EthereumOutboundQueue, - >, - XcmFeeToAccount, - ), - >; - type MessageExporter = - (ToBridgeHubKusamaHaulBlobExporter, crate::bridge_to_ethereum_config::SnowbridgeExporter); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = Nothing; - type TransactionalProcessor = FrameTransactionalProcessor; + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = FungibleTransactor; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + // BridgeHub does not recognize a reserve location for any asset. Users must teleport DOT + // where allowed (e.g. with the Relay Chain). + type IsReserve = (); + type IsTeleporter = TrustedTeleporters; + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = WeightInfoBounds< + crate::weights::xcm::BridgeHubPolkadotXcmWeight, + RuntimeCall, + MaxInstructions, + >; + type Trader = UsingComponents< + WeightToFee, + DotRelayLocation, + AccountId, + Balances, + ResolveTo, + >; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = XcmFeeManagerFromComponentsBridgeHub< + WaivedLocations, + ( + XcmExportFeeToSibling< + bp_polkadot::Balance, + AccountId, + DotRelayLocation, + EthereumNetwork, + Self::AssetTransactor, + crate::EthereumOutboundQueue, + >, + XcmFeeToAccount, + ), + >; + type MessageExporter = crate::bridge_to_ethereum_config::SnowbridgeExporter; + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; + type Aliasers = Nothing; + type TransactionalProcessor = FrameTransactionalProcessor; } /// Converts a local signed origin into an XCM location. @@ -253,70 +252,70 @@ pub type LocalOriginToLocation = SignedToAccountId32, - // ..and XCMP to communicate with the sibling chains. - XcmpQueue, + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, )>; impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - // We want to disallow users sending (arbitrary) XCMs from this chain. - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - // We support local origins dispatching XCM executions in principle... - type ExecuteXcmOrigin = EnsureXcmOrigin; - // ... but disallow generic XCM execution. As a result only teleports are allowed. - type XcmExecuteFilter = Nothing; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Nothing; // This parachain is not meant as a reserve location. - type Weigher = WeightInfoBounds< - crate::weights::xcm::BridgeHubPolkadotXcmWeight, - RuntimeCall, - MaxInstructions, - >; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; - type MaxLockers = ConstU32<8>; - type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); + type RuntimeEvent = RuntimeEvent; + // We want to disallow users sending (arbitrary) XCMs from this chain. + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // We support local origins dispatching XCM executions in principle... + type ExecuteXcmOrigin = EnsureXcmOrigin; + // ... but disallow generic XCM execution. As a result only teleports are allowed. + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Nothing; // This parachain is not meant as a reserve location. + type Weigher = WeightInfoBounds< + crate::weights::xcm::BridgeHubPolkadotXcmWeight, + RuntimeCall, + MaxInstructions, + >; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type WeightInfo = crate::weights::pallet_xcm::WeightInfo; + type AdminOrigin = EnsureRoot; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); } impl cumulus_pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; } /// A `FeeManager` implementation that forces fees for any message delivered to Ethereum. /// Otherwise, it permits the specified `WaivedLocations` to not pay for fees and uses the provided /// `HandleFee` implementation. pub struct XcmFeeManagerFromComponentsBridgeHub( - PhantomData<(WaivedLocations, HandleFee)>, + PhantomData<(WaivedLocations, HandleFee)>, ); impl, FeeHandler: HandleFee> FeeManager - for XcmFeeManagerFromComponentsBridgeHub +for XcmFeeManagerFromComponentsBridgeHub { - fn is_waived(origin: Option<&Location>, fee_reason: FeeReason) -> bool { - let Some(loc) = origin else { return false }; - if let Export { network, destination: Here } = fee_reason { - if network == EthereumNetwork::get() { - return false - } - } - WaivedLocations::contains(loc) - } + fn is_waived(origin: Option<&Location>, fee_reason: FeeReason) -> bool { + let Some(loc) = origin else { return false }; + if let Export { network, destination: Here } = fee_reason { + if network == EthereumNetwork::get() { + return false + } + } + WaivedLocations::contains(loc) + } - fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) { - FeeHandler::handle_fee(fee, context, reason); - } + fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) { + FeeHandler::handle_fee(fee, context, reason); + } } diff --git a/system-parachains/bridge-hub-paseo/tests/snowbridge.rs b/system-parachains/bridge-hub-paseo/tests/snowbridge.rs index 552841e..de47f3c 100644 --- a/system-parachains/bridge-hub-paseo/tests/snowbridge.rs +++ b/system-parachains/bridge-hub-paseo/tests/snowbridge.rs @@ -17,27 +17,26 @@ #![cfg(test)] use bp_polkadot_core::Signature; -use bridge_hub_polkadot_runtime::{ - bridge_to_ethereum_config::{EthereumGatewayAddress, EthereumNetwork}, - bridge_to_kusama_config::RefundBridgeHubKusamaMessages, - xcm_config::{XcmConfig, XcmFeeManagerFromComponentsBridgeHub}, - BridgeRejectObsoleteHeadersAndMessages, Executive, MessageQueueServiceWeight, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, SignedExtra, UncheckedExtrinsic, +use bridge_hub_paseo_runtime::{ + bridge_to_ethereum_config::{EthereumGatewayAddress, EthereumNetwork}, + xcm_config::{XcmConfig, XcmFeeManagerFromComponentsBridgeHub}, + Executive, MessageQueueServiceWeight, Runtime, + RuntimeCall, RuntimeEvent, SessionKeys, SignedExtra, UncheckedExtrinsic, }; use bridge_hub_test_utils::ValidatorIdOf; use codec::{Decode, Encode}; use cumulus_primitives_core::XcmError::{FailedToTransactAsset, NotHoldingFees}; use frame_support::{ - assert_err, assert_ok, parameter_types, - traits::{Contains, OnFinalize, OnInitialize}, + assert_err, assert_ok, parameter_types, + traits::{Contains, OnFinalize, OnInitialize}, }; use frame_system::pallet_prelude::BlockNumberFor; use parachains_common::{AccountId, AuraId, Balance}; pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_governance_works; use parachains_runtimes_test_utils::{ - AccountIdOf, CollatorSessionKeys, ExtBuilder, XcmReceivedFrom, + AccountIdOf, CollatorSessionKeys, ExtBuilder, XcmReceivedFrom, }; -use polkadot_runtime_constants::currency::UNITS; +use paseo_runtime_constants::currency::UNITS; use snowbridge_core::{gwei, meth, ChannelId, ParaId, Rewards}; use snowbridge_pallet_ethereum_client::WeightInfo; use snowbridge_pallet_system::{PricingParametersOf, WeightInfo as EthereumSystemWeightInfo}; @@ -45,462 +44,460 @@ use snowbridge_runtime_test_common::initial_fund; use sp_core::H160; use sp_keyring::AccountKeyring::Alice; use sp_runtime::{ - generic::{Era, SignedPayload}, - traits::Header, - AccountId32, FixedU128, Saturating, + generic::{Era, SignedPayload}, + traits::Header, + AccountId32, FixedU128, Saturating, }; use xcm::{latest::prelude::*, v3::Error}; use xcm_builder::HandleFee; use xcm_executor::{ - traits::{FeeManager, FeeReason}, - XcmExecutor, + traits::{FeeManager, FeeReason}, + XcmExecutor, }; type RuntimeHelper = - parachains_runtimes_test_utils::RuntimeHelper; +parachains_runtimes_test_utils::RuntimeHelper; parameter_types! { pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000; } fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys { - bridge_hub_test_utils::CollatorSessionKeys::new( - AccountId::from(Alice), - AccountId::from(Alice), - SessionKeys { aura: AuraId::from(Alice.public()) }, - ) + bridge_hub_test_utils::CollatorSessionKeys::new( + AccountId::from(Alice), + AccountId::from(Alice), + SessionKeys { aura: AuraId::from(Alice.public()) }, + ) } #[test] pub fn transfer_token_to_ethereum_works() { - send_transfer_token_message_success::( - collator_session_keys(), - 1013, - 1000, - H160::random(), - H160::random(), - DefaultBridgeHubEthereumBaseFee::get(), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::EthereumOutboundQueue(event)) => Some(event), - _ => None, - } - }), - ) + send_transfer_token_message_success::( + collator_session_keys(), + 1013, + 1000, + H160::random(), + H160::random(), + DefaultBridgeHubEthereumBaseFee::get(), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::EthereumOutboundQueue(event)) => Some(event), + _ => None, + } + }), + ) } #[test] pub fn unpaid_transfer_token_to_ethereum_fails_with_barrier() { - snowbridge_runtime_test_common::send_unpaid_transfer_token_message::( - collator_session_keys(), - 1013, - 1000, - H160::random(), - H160::random(), - ) + snowbridge_runtime_test_common::send_unpaid_transfer_token_message::( + collator_session_keys(), + 1013, + 1000, + H160::random(), + H160::random(), + ) } #[test] pub fn transfer_token_to_ethereum_fee_not_enough() { - send_transfer_token_message_failure::( - collator_session_keys(), - 1013, - 1000, - DefaultBridgeHubEthereumBaseFee::get() + 1_000_000_000, - H160::random(), - H160::random(), - // fee not enough - 1_000_000_000, - Box::new(|call| RuntimeCall::EthereumSystem(call).encode()), - NotHoldingFees, - ) + send_transfer_token_message_failure::( + collator_session_keys(), + 1013, + 1000, + DefaultBridgeHubEthereumBaseFee::get() + 1_000_000_000, + H160::random(), + H160::random(), + // fee not enough + 1_000_000_000, + Box::new(|call| RuntimeCall::EthereumSystem(call).encode()), + NotHoldingFees, + ) } #[test] pub fn transfer_token_to_ethereum_insufficient_fund() { - send_transfer_token_message_failure::( - collator_session_keys(), - 1013, - 1000, - 1_000_000_000, - H160::random(), - H160::random(), - DefaultBridgeHubEthereumBaseFee::get(), - Box::new(|call| RuntimeCall::EthereumSystem(call).encode()), - FailedToTransactAsset("Funds are unavailable"), - ) + send_transfer_token_message_failure::( + collator_session_keys(), + 1013, + 1000, + 1_000_000_000, + H160::random(), + H160::random(), + DefaultBridgeHubEthereumBaseFee::get(), + Box::new(|call| RuntimeCall::EthereumSystem(call).encode()), + FailedToTransactAsset("Funds are unavailable"), + ) } #[test] fn change_ethereum_gateway_by_governance_works() { - change_storage_constant_by_governance_works::( - collator_session_keys(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), - || (EthereumGatewayAddress::key().to_vec(), EthereumGatewayAddress::get()), - |_| [1; 20].into(), - ) + change_storage_constant_by_governance_works::( + collator_session_keys(), + bp_bridge_hub_paseo::BRIDGE_HUB_PASEO_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (EthereumGatewayAddress::key().to_vec(), EthereumGatewayAddress::get()), + |_| [1; 20].into(), + ) } /// Fee is not waived when origin is none. #[test] fn test_xcm_fee_manager_from_components_bh_origin_none() { - assert!(!TestXcmFeeManager::is_waived(None, FeeReason::ChargeFees)); + assert!(!TestXcmFeeManager::is_waived(None, FeeReason::ChargeFees)); } /// Fee is not waived when origin is not in waived location. #[test] fn test_xcm_fee_manager_from_components_bh_origin_not_in_waived_locations() { - assert!(!TestXcmFeeManager::is_waived( - Some(&Location::new(1, [Parachain(1)])), - FeeReason::DepositReserveAsset - )); + assert!(!TestXcmFeeManager::is_waived( + Some(&Location::new(1, [Parachain(1)])), + FeeReason::DepositReserveAsset + )); } /// Fee is waived when origin is in waived location. #[test] fn test_xcm_fee_manager_from_components_bh_origin_in_waived_locations() { - assert!(TestXcmFeeManager::is_waived( - Some(&Location::new(1, [Parachain(2)])), - FeeReason::DepositReserveAsset - )); + assert!(TestXcmFeeManager::is_waived( + Some(&Location::new(1, [Parachain(2)])), + FeeReason::DepositReserveAsset + )); } /// Fee is waived when origin is in waived location with Export message, but not to Ethereum. #[test] -fn test_xcm_fee_manager_from_components_bh_origin_in_waived_locations_with_export_to_polkadot_reason( +fn test_xcm_fee_manager_from_components_bh_origin_in_waived_locations_with_export_to_paseo_reason( ) { - assert!(TestXcmFeeManager::is_waived( - Some(&Location::new(1, [Parachain(2)])), - FeeReason::Export { network: Polkadot, destination: Here } - )); + assert!(TestXcmFeeManager::is_waived( + Some(&Location::new(1, [Parachain(2)])), + FeeReason::Export { network: Polkadot, destination: Here } + )); } /// Fee is not waived when origin is in waived location but exported to Ethereum. #[test] fn test_xcm_fee_manager_from_components_bh_in_waived_locations_with_export_to_ethereum_reason() { - assert!(!TestXcmFeeManager::is_waived( - Some(&Location::new(1, [Parachain(1)])), - FeeReason::Export { network: EthereumNetwork::get(), destination: Here } - )); + assert!(!TestXcmFeeManager::is_waived( + Some(&Location::new(1, [Parachain(1)])), + FeeReason::Export { network: EthereumNetwork::get(), destination: Here } + )); } struct MockWaivedLocations; impl Contains for MockWaivedLocations { - fn contains(loc: &Location) -> bool { - loc == &Location::new(1, [Parachain(2)]) - } + fn contains(loc: &Location) -> bool { + loc == &Location::new(1, [Parachain(2)]) + } } struct MockFeeHandler; impl HandleFee for MockFeeHandler { - fn handle_fee(fee: Assets, _context: Option<&XcmContext>, _reason: FeeReason) -> Assets { - fee - } + fn handle_fee(fee: Assets, _context: Option<&XcmContext>, _reason: FeeReason) -> Assets { + fee + } } type TestXcmFeeManager = XcmFeeManagerFromComponentsBridgeHub; #[allow(clippy::too_many_arguments)] pub fn send_transfer_token_message_failure( - collator_session_key: CollatorSessionKeys, - runtime_para_id: u32, - assethub_parachain_id: u32, - initial_amount: u128, - weth_contract_address: H160, - destination_address: H160, - fee_amount: u128, - system_call_encode: Box) -> Vec>, - expected_error: Error, + collator_session_key: CollatorSessionKeys, + runtime_para_id: u32, + assethub_parachain_id: u32, + initial_amount: u128, + weth_contract_address: H160, + destination_address: H160, + fee_amount: u128, + system_call_encode: Box) -> Vec>, + expected_error: Error, ) where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config - + snowbridge_pallet_system::Config, - XcmConfig: xcm_executor::Config, - ValidatorIdOf: From>, - <::Token as frame_support::traits::fungible::Inspect<::AccountId>>::Balance: From + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + snowbridge_pallet_outbound_queue::Config + + snowbridge_pallet_system::Config, + XcmConfig: xcm_executor::Config, + ValidatorIdOf: From>, + <::Token as frame_support::traits::fungible::Inspect<::AccountId>>::Balance: From { - ExtBuilder::::default() - .with_collators(collator_session_key.collators()) - .with_session_keys(collator_session_key.session_keys()) - .with_para_id(runtime_para_id.into()) - .with_tracing() - .build() - .execute_with(|| { - assert_ok!(>::initialize( + ExtBuilder::::default() + .with_collators(collator_session_key.collators()) + .with_session_keys(collator_session_key.session_keys()) + .with_para_id(runtime_para_id.into()) + .with_tracing() + .build() + .execute_with(|| { + assert_ok!(>::initialize( runtime_para_id.into(), assethub_parachain_id.into(), )); - let require_weight_at_most = - ::WeightInfo::set_pricing_parameters(); - - let set_pricing_parameters_call = system_call_encode(snowbridge_pallet_system::Call::< - Runtime, - >::set_pricing_parameters { - params: { - PricingParametersOf:: { - exchange_rate: FixedU128::from_rational(1, 75), - fee_per_gas: gwei(20), - rewards: Rewards { - local: (UNITS / 100).into(), // 0.01 DOT - remote: meth(1), - }, - multiplier: FixedU128::from_rational(1, 1), - } - }, - }); - - assert_ok!(RuntimeHelper::::execute_as_governance( + let require_weight_at_most = + ::WeightInfo::set_pricing_parameters(); + + let set_pricing_parameters_call = system_call_encode(snowbridge_pallet_system::Call::< + Runtime, + >::set_pricing_parameters { + params: { + PricingParametersOf:: { + exchange_rate: FixedU128::from_rational(1, 75), + fee_per_gas: gwei(20), + rewards: Rewards { + local: (UNITS / 100).into(), // 0.01 DOT + remote: meth(1), + }, + multiplier: FixedU128::from_rational(1, 1), + } + }, + }); + + assert_ok!(RuntimeHelper::::execute_as_governance( set_pricing_parameters_call, require_weight_at_most ) .ensure_complete()); - // fund asset hub sovereign account enough so it can pay fees - initial_fund::(assethub_parachain_id, initial_amount); - - let outcome = send_transfer_token_message::( - assethub_parachain_id, - weth_contract_address, - destination_address, - fee_amount, - ); - assert_err!(outcome.ensure_complete(), expected_error); - }); + // fund asset hub sovereign account enough so it can pay fees + initial_fund::(assethub_parachain_id, initial_amount); + + let outcome = send_transfer_token_message::( + assethub_parachain_id, + weth_contract_address, + destination_address, + fee_amount, + ); + assert_err!(outcome.ensure_complete(), expected_error); + }); } #[test] fn max_message_queue_service_weight_is_more_than_beacon_extrinsic_weights() { - let max_message_queue_weight = MessageQueueServiceWeight::get(); - let force_checkpoint = - ::WeightInfo::force_checkpoint(); - let submit_checkpoint = - ::WeightInfo::submit(); - max_message_queue_weight.all_gt(force_checkpoint); - max_message_queue_weight.all_gt(submit_checkpoint); + let max_message_queue_weight = MessageQueueServiceWeight::get(); + let force_checkpoint = + ::WeightInfo::force_checkpoint(); + let submit_checkpoint = + ::WeightInfo::submit(); + max_message_queue_weight.all_gt(force_checkpoint); + max_message_queue_weight.all_gt(submit_checkpoint); } #[test] fn ethereum_client_consensus_extrinsics_work() { - snowbridge_runtime_test_common::ethereum_extrinsic( - collator_session_keys(), - 1013, - construct_and_apply_extrinsic, - ); + snowbridge_runtime_test_common::ethereum_extrinsic( + collator_session_keys(), + 1013, + construct_and_apply_extrinsic, + ); } #[test] -fn ethereum_to_polkadot_message_extrinsics_work() { - snowbridge_runtime_test_common::ethereum_to_polkadot_message_extrinsics_work( - collator_session_keys(), - 1013, - construct_and_apply_extrinsic, - ); +fn ethereum_to_paseo_message_extrinsics_work() { + snowbridge_runtime_test_common::ethereum_to_polkadot_message_extrinsics_work( + collator_session_keys(), + 1013, + construct_and_apply_extrinsic, + ); } #[test] fn ethereum_outbound_queue_processes_messages_before_message_queue_works() { - // TODO: add test after dependencies are upgraded to >= 1.8 + // TODO: add test after dependencies are upgraded to >= 1.8 } fn construct_extrinsic( - sender: sp_keyring::AccountKeyring, - call: RuntimeCall, + sender: sp_keyring::AccountKeyring, + call: RuntimeCall, ) -> UncheckedExtrinsic { - let account_id = AccountId32::from(sender.public()); - let extra: SignedExtra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::immortal()), - frame_system::CheckNonce::::from( - frame_system::Pallet::::account(&account_id).nonce, - ), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - BridgeRejectObsoleteHeadersAndMessages, - (RefundBridgeHubKusamaMessages::default()), - frame_metadata_hash_extension::CheckMetadataHash::::new(false), - ); - let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); - let signature = payload.using_encoded(|e| sender.sign(e)); - UncheckedExtrinsic::new_signed( - call, - account_id.into(), - Signature::Sr25519(signature.clone()), - extra, - ) + let account_id = AccountId32::from(sender.public()); + let extra: SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::immortal()), + frame_system::CheckNonce::::from( + frame_system::Pallet::::account(&account_id).nonce, + ), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + frame_metadata_hash_extension::CheckMetadataHash::::new(false), + ); + let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::new_signed( + call, + account_id.into(), + Signature::Sr25519(signature.clone()), + extra, + ) } fn construct_and_apply_extrinsic( - origin: sp_keyring::AccountKeyring, - call: RuntimeCall, + origin: sp_keyring::AccountKeyring, + call: RuntimeCall, ) -> sp_runtime::DispatchOutcome { - let xt = construct_extrinsic(origin, call); - let r = Executive::apply_extrinsic(xt); - r.unwrap() + let xt = construct_extrinsic(origin, call); + let r = Executive::apply_extrinsic(xt); + r.unwrap() } // TODO remove when Ethereum network ID has been extracted as a param pub fn send_transfer_token_message( - assethub_parachain_id: u32, - weth_contract_address: H160, - destination_address: H160, - fee_amount: u128, + assethub_parachain_id: u32, + weth_contract_address: H160, + destination_address: H160, + fee_amount: u128, ) -> Outcome -where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config, - XcmConfig: xcm_executor::Config, + where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + snowbridge_pallet_outbound_queue::Config, + XcmConfig: xcm_executor::Config, { - let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id)); - let asset = Asset { - id: AssetId(Location::new( - 0, - [AccountKey20 { network: None, key: weth_contract_address.into() }], - )), - fun: Fungible(1000000000), - }; - let assets = vec![asset.clone()]; - - let inner_xcm = Xcm(vec![ - WithdrawAsset(Assets::from(assets.clone())), - ClearOrigin, - BuyExecution { fees: asset, weight_limit: Unlimited }, - DepositAsset { - assets: Wild(All), - beneficiary: Location::new( - 0, - [AccountKey20 { network: None, key: destination_address.into() }], - ), - }, - SetTopic([0; 32]), - ]); - - let fee = - Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(fee_amount) }; - - // prepare transfer token message - let xcm = Xcm(vec![ - WithdrawAsset(Assets::from(vec![fee.clone()])), - BuyExecution { fees: fee, weight_limit: Unlimited }, - ExportMessage { network: Ethereum { chain_id: 1 }, destination: Here, xcm: inner_xcm }, - ]); - - // execute XCM - let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); - XcmExecutor::::prepare_and_execute( - assethub_parachain_location, - xcm, - &mut hash, - RuntimeHelper::::xcm_max_weight(XcmReceivedFrom::Sibling), - Weight::zero(), - ) + let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id)); + let asset = Asset { + id: AssetId(Location::new( + 0, + [AccountKey20 { network: None, key: weth_contract_address.into() }], + )), + fun: Fungible(1000000000), + }; + let assets = vec![asset.clone()]; + + let inner_xcm = Xcm(vec![ + WithdrawAsset(Assets::from(assets.clone())), + ClearOrigin, + BuyExecution { fees: asset, weight_limit: Unlimited }, + DepositAsset { + assets: Wild(All), + beneficiary: Location::new( + 0, + [AccountKey20 { network: None, key: destination_address.into() }], + ), + }, + SetTopic([0; 32]), + ]); + + let fee = + Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(fee_amount) }; + + // prepare transfer token message + let xcm = Xcm(vec![ + WithdrawAsset(Assets::from(vec![fee.clone()])), + BuyExecution { fees: fee, weight_limit: Unlimited }, + ExportMessage { network: Ethereum { chain_id: 11155111 }, destination: Here, xcm: inner_xcm }, + ]); + + // execute XCM + let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); + XcmExecutor::::prepare_and_execute( + assethub_parachain_location, + xcm, + &mut hash, + RuntimeHelper::::xcm_max_weight(XcmReceivedFrom::Sibling), + Weight::zero(), + ) } pub fn send_transfer_token_message_success( - collator_session_key: CollatorSessionKeys, - runtime_para_id: u32, - assethub_parachain_id: u32, - weth_contract_address: H160, - destination_address: H160, - fee_amount: u128, - snowbridge_pallet_outbound_queue: Box< - dyn Fn(Vec) -> Option>, - >, + collator_session_key: CollatorSessionKeys, + runtime_para_id: u32, + assethub_parachain_id: u32, + weth_contract_address: H160, + destination_address: H160, + fee_amount: u128, + snowbridge_pallet_outbound_queue: Box< + dyn Fn(Vec) -> Option>, + >, ) where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + pallet_message_queue::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config - + snowbridge_pallet_system::Config, - XcmConfig: xcm_executor::Config, - ValidatorIdOf: From>, - ::AccountId: From + AsRef<[u8]>, + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + pallet_message_queue::Config + + cumulus_pallet_parachain_system::Config + + snowbridge_pallet_outbound_queue::Config + + snowbridge_pallet_system::Config, + XcmConfig: xcm_executor::Config, + ValidatorIdOf: From>, + ::AccountId: From + AsRef<[u8]>, { - ExtBuilder::::default() - .with_collators(collator_session_key.collators()) - .with_session_keys(collator_session_key.session_keys()) - .with_para_id(runtime_para_id.into()) - .with_tracing() - .build() - .execute_with(|| { - >::initialize( - runtime_para_id.into(), - assethub_parachain_id.into(), - ) - .unwrap(); - - // fund asset hub sovereign account enough so it can pay fees - initial_fund::(assethub_parachain_id, 5_000_000_000_000); - - let outcome = send_transfer_token_message::( - assethub_parachain_id, - weth_contract_address, - destination_address, - fee_amount, - ); - - assert_ok!(outcome.ensure_complete()); - - // check events - let mut events = >::events() - .into_iter() - .filter_map(|e| snowbridge_pallet_outbound_queue(e.event.encode())); - assert!(events.any(|e| matches!( + ExtBuilder::::default() + .with_collators(collator_session_key.collators()) + .with_session_keys(collator_session_key.session_keys()) + .with_para_id(runtime_para_id.into()) + .with_tracing() + .build() + .execute_with(|| { + >::initialize( + runtime_para_id.into(), + assethub_parachain_id.into(), + ) + .unwrap(); + + // fund asset hub sovereign account enough so it can pay fees + initial_fund::(assethub_parachain_id, 5_000_000_000_000); + + let outcome = send_transfer_token_message::( + assethub_parachain_id, + weth_contract_address, + destination_address, + fee_amount, + ); + + assert_ok!(outcome.ensure_complete()); + + // check events + let mut events = >::events() + .into_iter() + .filter_map(|e| snowbridge_pallet_outbound_queue(e.event.encode())); + assert!(events.any(|e| matches!( e, snowbridge_pallet_outbound_queue::Event::MessageQueued { .. } ))); - let block_number = >::block_number(); - let next_block_number = >::block_number() - .saturating_add(BlockNumberFor::::from(1u32)); + let block_number = >::block_number(); + let next_block_number = >::block_number() + .saturating_add(BlockNumberFor::::from(1u32)); - // finish current block - >::on_finalize(block_number); - >::on_finalize(block_number); - >::on_finalize(block_number); + // finish current block + >::on_finalize(block_number); + >::on_finalize(block_number); + >::on_finalize(block_number); - // start next block - >::set_block_number(next_block_number); - >::on_initialize(next_block_number); - >::on_initialize(next_block_number); - >::on_initialize(next_block_number); + // start next block + >::set_block_number(next_block_number); + >::on_initialize(next_block_number); + >::on_initialize(next_block_number); + >::on_initialize(next_block_number); - // finish next block - >::on_finalize(next_block_number); - >::on_finalize(next_block_number); - let included_head = >::finalize(); + // finish next block + >::on_finalize(next_block_number); + >::on_finalize(next_block_number); + let included_head = >::finalize(); - let origin: ParaId = assethub_parachain_id.into(); - let channel_id: ChannelId = origin.into(); + let origin: ParaId = assethub_parachain_id.into(); + let channel_id: ChannelId = origin.into(); - let nonce = snowbridge_pallet_outbound_queue::Nonce::::try_get(channel_id); - assert_ok!(nonce); - assert_eq!(nonce.unwrap(), 1); + let nonce = snowbridge_pallet_outbound_queue::Nonce::::try_get(channel_id); + assert_ok!(nonce); + assert_eq!(nonce.unwrap(), 1); - let digest = included_head.digest(); + let digest = included_head.digest(); - let digest_items = digest.logs(); - assert!(digest_items.len() == 1 && digest_items[0].as_other().is_some()); - }); + let digest_items = digest.logs(); + assert!(digest_items.len() == 1 && digest_items[0].as_other().is_some()); + }); } diff --git a/system-parachains/bridge-hub-paseo/tests/tests.rs b/system-parachains/bridge-hub-paseo/tests/tests.rs deleted file mode 100644 index a2b5628..0000000 --- a/system-parachains/bridge-hub-paseo/tests/tests.rs +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Cumulus is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Cumulus. If not, see . - -use bp_bridge_hub_kusama::Perbill; -use bp_polkadot_core::Signature; -use bridge_hub_polkadot_runtime::{ - bridge_to_kusama_config::{ - AssetHubKusamaParaId, BridgeGrandpaKusamaInstance, BridgeHubKusamaChainId, - BridgeHubKusamaLocation, BridgeParachainKusamaInstance, DeliveryRewardInBalance, - KusamaGlobalConsensusNetwork, RefundBridgeHubKusamaMessages, RequiredStakeForStakeAndSlash, - WithBridgeHubKusamaMessageBridge, WithBridgeHubKusamaMessagesInstance, - XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA, - }, - xcm_config::{ - DotRelayLocation, LocationToAccountId, RelayNetwork, RelayTreasuryLocation, - RelayTreasuryPalletAccount, XcmConfig, - }, - AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit, - ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, - SignedExtra, TransactionPayment, UncheckedExtrinsic, SLOT_DURATION, -}; -use bridge_hub_test_utils::{test_cases::from_parachain, SlotDurations}; -use codec::{Decode, Encode}; -use frame_support::{dispatch::GetDispatchInfo, parameter_types, traits::ConstU8}; -use parachains_common::{AccountId, AuraId, Balance}; -use sp_consensus_aura::SlotDuration; -use sp_keyring::AccountKeyring::Alice; -use sp_runtime::{ - generic::{Era, SignedPayload}, - AccountId32, -}; -use system_parachains_constants::polkadot::{ - consensus::RELAY_CHAIN_SLOT_DURATION_MILLIS, fee::WeightToFee, -}; -use xcm::latest::prelude::*; -use xcm_executor::traits::ConvertLocation; - -// Para id of sibling chain used in tests. -pub const SIBLING_PARACHAIN_ID: u32 = 1000; - -// Runtime from tests PoV -type RuntimeTestsAdapter = from_parachain::WithRemoteParachainHelperAdapter< - Runtime, - AllPalletsWithoutSystem, - BridgeGrandpaKusamaInstance, - BridgeParachainKusamaInstance, - WithBridgeHubKusamaMessagesInstance, - WithBridgeHubKusamaMessageBridge, ->; - -parameter_types! { - pub CheckingAccount: AccountId = PolkadotXcm::check_account(); -} - -fn construct_extrinsic( - sender: sp_keyring::AccountKeyring, - call: RuntimeCall, -) -> UncheckedExtrinsic { - let account_id = AccountId32::from(sender.public()); - let extra: SignedExtra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::immortal()), - frame_system::CheckNonce::::from( - frame_system::Pallet::::account(&account_id).nonce, - ), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - BridgeRejectObsoleteHeadersAndMessages, - (RefundBridgeHubKusamaMessages::default()), - frame_metadata_hash_extension::CheckMetadataHash::::new(false), - ); - let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); - let signature = payload.using_encoded(|e| sender.sign(e)); - UncheckedExtrinsic::new_signed( - call, - account_id.into(), - Signature::Sr25519(signature.clone()), - extra, - ) -} - -fn construct_and_apply_extrinsic( - relayer_at_target: sp_keyring::AccountKeyring, - call: RuntimeCall, -) -> sp_runtime::DispatchOutcome { - let xt = construct_extrinsic(relayer_at_target, call); - let r = Executive::apply_extrinsic(xt); - r.unwrap() -} - -fn construct_and_estimate_extrinsic_fee(batch: pallet_utility::Call) -> Balance { - let batch_call = RuntimeCall::Utility(batch); - let batch_info = batch_call.get_dispatch_info(); - let xt = construct_extrinsic(Alice, batch_call); - TransactionPayment::compute_fee(xt.encoded_size() as _, &batch_info, 0) -} - -fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys { - bridge_hub_test_utils::CollatorSessionKeys::new( - AccountId::from(Alice), - AccountId::from(Alice), - SessionKeys { aura: AuraId::from(Alice.public()) }, - ) -} - -fn slot_durations() -> SlotDurations { - SlotDurations { - relay: SlotDuration::from_millis(RELAY_CHAIN_SLOT_DURATION_MILLIS.into()), - para: SlotDuration::from_millis(SLOT_DURATION), - } -} - -bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( - Runtime, - AllPalletsWithoutSystem, - XcmConfig, - CheckingAccount, - WeightToFee, - ParachainSystem, - collator_session_keys(), - slot_durations(), - ExistentialDeposit::get(), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), - _ => None, - } - }), - 1002 -); - -#[test] -fn test_ed_is_one_tenth_of_relay() { - let relay_ed = polkadot_runtime_constants::currency::EXISTENTIAL_DEPOSIT; - let bridge_hub_ed = ExistentialDeposit::get(); - assert_eq!(relay_ed / 10, bridge_hub_ed); -} - -#[test] -fn initialize_bridge_by_governance_works() { - bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< - Runtime, - BridgeGrandpaKusamaInstance, - >(collator_session_keys(), bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID) -} - -#[test] -fn change_bridge_grandpa_pallet_mode_by_governance_works() { - // for Kusama finality - bridge_hub_test_utils::test_cases::change_bridge_grandpa_pallet_mode_by_governance_works::< - Runtime, - BridgeGrandpaKusamaInstance, - >(collator_session_keys(), bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID) -} - -#[test] -fn change_bridge_parachains_pallet_mode_by_governance_works() { - // for Kusama parachains finality - bridge_hub_test_utils::test_cases::change_bridge_parachains_pallet_mode_by_governance_works::< - Runtime, - BridgeParachainKusamaInstance, - >(collator_session_keys(), bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID) -} - -#[test] -fn change_bridge_messages_pallet_mode_by_governance_works() { - // for Kusama messages - bridge_hub_test_utils::test_cases::change_bridge_messages_pallet_mode_by_governance_works::< - Runtime, - WithBridgeHubKusamaMessagesInstance, - >(collator_session_keys(), bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID) -} - -#[test] -fn change_delivery_reward_by_governance_works() { - bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< - Runtime, - DeliveryRewardInBalance, - Balance, - >( - collator_session_keys(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), - || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), - |old_value| old_value.checked_mul(2).unwrap(), - ) -} - -#[test] -fn change_required_stake_by_governance_works() { - bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< - Runtime, - RequiredStakeForStakeAndSlash, - Balance, - >( - collator_session_keys(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - Box::new(|call| RuntimeCall::System(call).encode()), - || (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()), - |old_value| old_value.checked_mul(2).unwrap(), - ) -} - -#[test] -fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { - bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< - Runtime, - XcmConfig, - WithBridgeHubKusamaMessagesInstance, - >( - collator_session_keys(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - SIBLING_PARACHAIN_ID, - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::BridgeKusamaMessages(event)) => Some(event), - _ => None, - } - }), - || ExportMessage { network: Kusama, destination: Parachain(AssetHubKusamaParaId::get().into()).into(), xcm: Xcm(vec![]) }, - XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA, - Some((DotRelayLocation::get(), ExistentialDeposit::get()).into()), - // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` - Some((DotRelayLocation::get(), bp_bridge_hub_polkadot::BridgeHubPolkadotBaseXcmFeeInDots::get()).into()), - || PolkadotXcm::force_xcm_version(RuntimeOrigin::root(), Box::new(BridgeHubKusamaLocation::get()), XCM_VERSION).expect("version saved!"), - ) -} - -#[test] -fn message_dispatch_routing_works() { - bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< - Runtime, - AllPalletsWithoutSystem, - XcmConfig, - ParachainSystem, - WithBridgeHubKusamaMessagesInstance, - RelayNetwork, - KusamaGlobalConsensusNetwork, - ConstU8<2>, - >( - collator_session_keys(), - slot_durations(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - SIBLING_PARACHAIN_ID, - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::ParachainSystem(event)) => Some(event), - _ => None, - } - }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), - XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA, - || (), - ) -} - -#[test] -fn relayed_incoming_message_works() { - from_parachain::relayed_incoming_message_works::( - collator_session_keys(), - slot_durations(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, - BridgeHubKusamaChainId::get(), - SIBLING_PARACHAIN_ID, - Polkadot, - XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA, - || (), - construct_and_apply_extrinsic, - ) -} - -#[test] -pub fn complex_relay_extrinsic_works() { - from_parachain::complex_relay_extrinsic_works::( - collator_session_keys(), - slot_durations(), - bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, - bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, - SIBLING_PARACHAIN_ID, - BridgeHubKusamaChainId::get(), - Polkadot, - XCM_LANE_FOR_ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA, - || (), - construct_and_apply_extrinsic, - ); -} - -#[test] -pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { - check_sane_fees_values( - "bp_bridge_hub_polkadot::BridgeHubPolkadotBaseXcmFeeInDots", - bp_bridge_hub_polkadot::BridgeHubPolkadotBaseXcmFeeInDots::get(), - || { - bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< - Runtime, - XcmConfig, - WeightToFee, - >() - }, - Perbill::from_percent(33), - Some(-33), - &format!( - "Estimate fee for `ExportMessage` for runtime: {:?}", - ::Version::get() - ), - ) -} - -#[test] -pub fn can_calculate_fee_for_complex_message_delivery_transaction() { - check_sane_fees_values( - "bp_bridge_hub_polkadot::BridgeHubPolkadotBaseDeliveryFeeInDots", - bp_bridge_hub_polkadot::BridgeHubPolkadotBaseDeliveryFeeInDots::get(), - || { - from_parachain::can_calculate_fee_for_complex_message_delivery_transaction::< - RuntimeTestsAdapter, - >(collator_session_keys(), construct_and_estimate_extrinsic_fee) - }, - Perbill::from_percent(33), - Some(-33), - &format!( - "Estimate fee for `single message delivery` for runtime: {:?}", - ::Version::get() - ), - ) -} - -#[test] -pub fn can_calculate_fee_for_complex_message_confirmation_transaction() { - check_sane_fees_values( - "bp_bridge_hub_polkadot::BridgeHubPolkadotBaseConfirmationFeeInDots", - bp_bridge_hub_polkadot::BridgeHubPolkadotBaseConfirmationFeeInDots::get(), - || { - from_parachain::can_calculate_fee_for_complex_message_confirmation_transaction::< - RuntimeTestsAdapter, - >(collator_session_keys(), construct_and_estimate_extrinsic_fee) - }, - Perbill::from_percent(33), - Some(-33), - &format!( - "Estimate fee for `single message confirmation` for runtime: {:?}", - ::Version::get() - ), - ) -} - -#[test] -fn treasury_pallet_account_not_none() { - assert_eq!( - RelayTreasuryPalletAccount::get(), - LocationToAccountId::convert_location(&RelayTreasuryLocation::get()).unwrap() - ) -} - -// TODO:(PR#159): remove when `polkadot-sdk@1.8.0` bump (https://github.com/polkadot-fellows/runtimes/issues/186) -/// A helper function for comparing the actual value of a fee constant with its estimated value. The -/// estimated value can be overestimated (`overestimate_in_percent`), and if the difference to the -/// actual value is below `margin_overestimate_diff_in_percent_for_lowering`, we should lower the -/// actual value. -pub fn check_sane_fees_values( - const_name: &str, - actual: u128, - calculate_estimated_fee: fn() -> u128, - overestimate_in_percent: Perbill, - margin_overestimate_diff_in_percent_for_lowering: Option, - label: &str, -) { - let estimated = calculate_estimated_fee(); - let estimated_plus_overestimate = estimated + (overestimate_in_percent * estimated); - let diff_to_estimated = diff_as_percent(actual, estimated); - let diff_to_estimated_plus_overestimate = diff_as_percent(actual, estimated_plus_overestimate); - - log::error!( - target: "bridges::estimate", - "{label}:\nconstant: {const_name}\n[+] actual: {actual}\n[+] estimated: {estimated} ({diff_to_estimated:.2?})\n[+] estimated(+33%): {estimated_plus_overestimate} ({diff_to_estimated_plus_overestimate:.2?})", - ); - - // check if estimated value is sane - assert!( - estimated <= actual, - "estimated: {estimated}, actual: {actual}, please adjust `{const_name}` to the value: {estimated_plus_overestimate}", - ); - assert!( - estimated_plus_overestimate <= actual, - "estimated_plus_overestimate: {estimated_plus_overestimate}, actual: {actual}, please adjust `{const_name}` to the value: {estimated_plus_overestimate}", - ); - - if let Some(margin_overestimate_diff_in_percent_for_lowering) = - margin_overestimate_diff_in_percent_for_lowering - { - assert!( - diff_to_estimated_plus_overestimate > margin_overestimate_diff_in_percent_for_lowering as f64, - "diff_to_estimated_plus_overestimate: {diff_to_estimated_plus_overestimate:.2}, overestimate_diff_in_percent_for_lowering: {margin_overestimate_diff_in_percent_for_lowering}, please adjust `{const_name}` to the value: {estimated_plus_overestimate}", - ); - } -} - -// TODO:(PR#159): remove when `polkadot-sdk@1.8.0` bump (https://github.com/polkadot-fellows/runtimes/issues/186) -pub fn diff_as_percent(left: u128, right: u128) -> f64 { - let left = left as f64; - let right = right as f64; - ((left - right).abs() / left) * 100f64 * (if left >= right { -1 } else { 1 }) as f64 -}